syscall.c 163.2 KB
Newer Older
1 2
/*
 *  Linux syscalls
3
 *
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *  Copyright (c) 2003 Fabrice Bellard
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
B
bellard 已提交
23
#include <string.h>
24 25 26 27 28
#include <elf.h>
#include <endian.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
B
bellard 已提交
29
#include <time.h>
30
#include <sys/types.h>
T
ths 已提交
31 32
#include <sys/ipc.h>
#include <sys/msg.h>
33 34 35 36
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/mount.h>
37
#include <sys/prctl.h>
38 39 40 41 42 43 44
#include <sys/resource.h>
#include <sys/mman.h>
#include <sys/swap.h>
#include <signal.h>
#include <sched.h>
#include <sys/socket.h>
#include <sys/uio.h>
B
bellard 已提交
45
#include <sys/poll.h>
B
bellard 已提交
46
#include <sys/times.h>
47
#include <sys/shm.h>
48
#include <sys/sem.h>
B
bellard 已提交
49
#include <sys/statfs.h>
50
#include <utime.h>
B
bellard 已提交
51
#include <sys/sysinfo.h>
B
bellard 已提交
52
//#include <sys/user.h>
53
#include <netinet/ip.h>
B
bellard 已提交
54
#include <netinet/tcp.h>
55 56 57 58

#define termios host_termios
#define winsize host_winsize
#define termio host_termio
B
bellard 已提交
59 60 61
#define sgttyb host_sgttyb /* same as target */
#define tchars host_tchars /* same as target */
#define ltchars host_ltchars /* same as target */
62 63 64 65 66 67 68

#include <linux/termios.h>
#include <linux/unistd.h>
#include <linux/utsname.h>
#include <linux/cdrom.h>
#include <linux/hdreg.h>
#include <linux/soundcard.h>
B
bellard 已提交
69
#include <linux/dirent.h>
B
bellard 已提交
70
#include <linux/kd.h>
71

B
bellard 已提交
72
#include "qemu.h"
73

B
bellard 已提交
74
//#define DEBUG
75

P
pbrook 已提交
76
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
77
    || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS)
78 79 80 81
/* 16 bit uid wrappers emulation */
#define USE_UID16
#endif

B
bellard 已提交
82 83 84 85
//#include <linux/msdos_fs.h>
#define	VFAT_IOCTL_READDIR_BOTH		_IOR('r', 1, struct dirent [2])
#define	VFAT_IOCTL_READDIR_SHORT	_IOR('r', 2, struct dirent [2])

86 87 88 89 90 91 92

#undef _syscall0
#undef _syscall1
#undef _syscall2
#undef _syscall3
#undef _syscall4
#undef _syscall5
B
bellard 已提交
93
#undef _syscall6
94

B
bellard 已提交
95 96 97 98 99
#define _syscall0(type,name)		\
type name (void)			\
{					\
	return syscall(__NR_##name);	\
}
100

B
bellard 已提交
101 102 103 104
#define _syscall1(type,name,type1,arg1)		\
type name (type1 arg1)				\
{						\
	return syscall(__NR_##name, arg1);	\
105 106
}

B
bellard 已提交
107 108 109 110
#define _syscall2(type,name,type1,arg1,type2,arg2)	\
type name (type1 arg1,type2 arg2)			\
{							\
	return syscall(__NR_##name, arg1, arg2);	\
111 112
}

B
bellard 已提交
113 114 115 116
#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)	\
type name (type1 arg1,type2 arg2,type3 arg3)			\
{								\
	return syscall(__NR_##name, arg1, arg2, arg3);		\
117 118
}

B
bellard 已提交
119 120 121 122
#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)	\
type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4)				\
{										\
	return syscall(__NR_##name, arg1, arg2, arg3, arg4);			\
123 124
}

B
bellard 已提交
125 126 127 128 129
#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,	\
		  type5,arg5)							\
type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5)		\
{										\
	return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5);		\
130 131
}

B
bellard 已提交
132 133 134 135 136 137

#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,	\
		  type5,arg5,type6,arg6)					\
type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6)	\
{										\
	return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6);	\
138
}
B
bellard 已提交
139

140

141
#define __NR_sys_uname __NR_uname
142
#define __NR_sys_faccessat __NR_faccessat
143
#define __NR_sys_fchmodat __NR_fchmodat
144
#define __NR_sys_fchownat __NR_fchownat
B
bellard 已提交
145 146
#define __NR_sys_getcwd1 __NR_getcwd
#define __NR_sys_getdents __NR_getdents
B
bellard 已提交
147
#define __NR_sys_getdents64 __NR_getdents64
148
#define __NR_sys_getpriority __NR_getpriority
149
#define __NR_sys_linkat __NR_linkat
150
#define __NR_sys_mkdirat __NR_mkdirat
151
#define __NR_sys_mknodat __NR_mknodat
152
#define __NR_sys_openat __NR_openat
153
#define __NR_sys_readlinkat __NR_readlinkat
154
#define __NR_sys_renameat __NR_renameat
B
bellard 已提交
155
#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
156
#define __NR_sys_symlinkat __NR_symlinkat
157
#define __NR_sys_syslog __NR_syslog
T
ths 已提交
158
#define __NR_sys_tgkill __NR_tgkill
T
ths 已提交
159
#define __NR_sys_tkill __NR_tkill
160
#define __NR_sys_unlinkat __NR_unlinkat
161
#define __NR_sys_utimensat __NR_utimensat
162

163
#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
B
bellard 已提交
164 165 166
#define __NR__llseek __NR_lseek
#endif

B
bellard 已提交
167
#ifdef __NR_gettid
168
_syscall0(int, gettid)
B
bellard 已提交
169
#else
170 171
/* This is a replacement for the host gettid() and must return a host
   errno. */
B
bellard 已提交
172 173 174 175
static int gettid(void) {
    return -ENOSYS;
}
#endif
176
_syscall1(int,sys_uname,struct new_utsname *,buf)
177 178 179
#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
_syscall4(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode,int,flags)
#endif
180 181 182 183
#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
_syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname,
          mode_t,mode,int,flags)
#endif
184 185 186 187
#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
          uid_t,owner,gid_t,group,int,flags)
#endif
B
bellard 已提交
188 189
_syscall2(int,sys_getcwd1,char *,buf,size_t,size)
_syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count);
T
ths 已提交
190
#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
B
bellard 已提交
191
_syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count);
T
ths 已提交
192
#endif
193
_syscall2(int, sys_getpriority, int, which, int, who);
194 195
_syscall5(int, _llseek,  uint,  fd, ulong, hi, ulong, lo,
          loff_t *, res, uint, wh);
196 197 198 199
#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
	  int,newdirfd,const char *,newpath,int,flags)
#endif
200 201 202
#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
#endif
203 204 205 206
#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
          mode_t,mode,dev_t,dev)
#endif
207 208 209
#if defined(TARGET_NR_openat) && defined(__NR_openat)
_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
#endif
210 211 212 213
#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
          char *,buf,size_t,bufsize)
#endif
214 215 216 217
#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
          int,newdirfd,const char *,newpath)
#endif
B
bellard 已提交
218
_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
219
#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
220 221 222
_syscall3(int,sys_symlinkat,const char *,oldpath,
          int,newdirfd,const char *,newpath)
#endif
223
_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
T
ths 已提交
224
#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
T
ths 已提交
225
_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
T
ths 已提交
226
#endif
T
ths 已提交
227
#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
T
ths 已提交
228 229
_syscall2(int,sys_tkill,int,tid,int,sig)
#endif
230 231 232
#ifdef __NR_exit_group
_syscall1(int,exit_group,int,error_code)
#endif
233 234 235
#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
_syscall1(int,set_tid_address,int *,tidptr)
#endif
236 237 238
#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
#endif
239 240 241 242
#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
          const struct timespec *,tsp,int,flags)
#endif
B
bellard 已提交
243 244

extern int personality(int);
B
bellard 已提交
245 246 247
extern int flock(int, int);
extern int setfsuid(int);
extern int setfsgid(int);
B
bellard 已提交
248 249 250 251
extern int setresuid(uid_t, uid_t, uid_t);
extern int getresuid(uid_t *, uid_t *, uid_t *);
extern int setresgid(gid_t, gid_t, gid_t);
extern int getresgid(gid_t *, gid_t *, gid_t *);
B
bellard 已提交
252
extern int setgroups(int, gid_t *);
253

254 255 256 257 258 259 260
#define ERRNO_TABLE_SIZE 1200

/* target_to_host_errno_table[] is initialized from
 * host_to_target_errno_table[] in syscall_init(). */
static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
};

261
/*
T
ths 已提交
262
 * This list is the union of errno values overridden in asm-<arch>/errno.h
263 264
 * minus the errnos that are not actually generic to all archs.
 */
265
static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
    [EIDRM]		= TARGET_EIDRM,
    [ECHRNG]		= TARGET_ECHRNG,
    [EL2NSYNC]		= TARGET_EL2NSYNC,
    [EL3HLT]		= TARGET_EL3HLT,
    [EL3RST]		= TARGET_EL3RST,
    [ELNRNG]		= TARGET_ELNRNG,
    [EUNATCH]		= TARGET_EUNATCH,
    [ENOCSI]		= TARGET_ENOCSI,
    [EL2HLT]		= TARGET_EL2HLT,
    [EDEADLK]		= TARGET_EDEADLK,
    [ENOLCK]		= TARGET_ENOLCK,
    [EBADE]		= TARGET_EBADE,
    [EBADR]		= TARGET_EBADR,
    [EXFULL]		= TARGET_EXFULL,
    [ENOANO]		= TARGET_ENOANO,
    [EBADRQC]		= TARGET_EBADRQC,
    [EBADSLT]		= TARGET_EBADSLT,
    [EBFONT]		= TARGET_EBFONT,
    [ENOSTR]		= TARGET_ENOSTR,
    [ENODATA]		= TARGET_ENODATA,
    [ETIME]		= TARGET_ETIME,
    [ENOSR]		= TARGET_ENOSR,
    [ENONET]		= TARGET_ENONET,
    [ENOPKG]		= TARGET_ENOPKG,
    [EREMOTE]		= TARGET_EREMOTE,
    [ENOLINK]		= TARGET_ENOLINK,
    [EADV]		= TARGET_EADV,
    [ESRMNT]		= TARGET_ESRMNT,
    [ECOMM]		= TARGET_ECOMM,
    [EPROTO]		= TARGET_EPROTO,
    [EDOTDOT]		= TARGET_EDOTDOT,
    [EMULTIHOP]		= TARGET_EMULTIHOP,
    [EBADMSG]		= TARGET_EBADMSG,
    [ENAMETOOLONG]	= TARGET_ENAMETOOLONG,
    [EOVERFLOW]		= TARGET_EOVERFLOW,
    [ENOTUNIQ]		= TARGET_ENOTUNIQ,
    [EBADFD]		= TARGET_EBADFD,
    [EREMCHG]		= TARGET_EREMCHG,
    [ELIBACC]		= TARGET_ELIBACC,
    [ELIBBAD]		= TARGET_ELIBBAD,
    [ELIBSCN]		= TARGET_ELIBSCN,
    [ELIBMAX]		= TARGET_ELIBMAX,
    [ELIBEXEC]		= TARGET_ELIBEXEC,
    [EILSEQ]		= TARGET_EILSEQ,
    [ENOSYS]		= TARGET_ENOSYS,
    [ELOOP]		= TARGET_ELOOP,
    [ERESTART]		= TARGET_ERESTART,
    [ESTRPIPE]		= TARGET_ESTRPIPE,
    [ENOTEMPTY]		= TARGET_ENOTEMPTY,
    [EUSERS]		= TARGET_EUSERS,
    [ENOTSOCK]		= TARGET_ENOTSOCK,
    [EDESTADDRREQ]	= TARGET_EDESTADDRREQ,
    [EMSGSIZE]		= TARGET_EMSGSIZE,
    [EPROTOTYPE]	= TARGET_EPROTOTYPE,
    [ENOPROTOOPT]	= TARGET_ENOPROTOOPT,
    [EPROTONOSUPPORT]	= TARGET_EPROTONOSUPPORT,
    [ESOCKTNOSUPPORT]	= TARGET_ESOCKTNOSUPPORT,
    [EOPNOTSUPP]	= TARGET_EOPNOTSUPP,
    [EPFNOSUPPORT]	= TARGET_EPFNOSUPPORT,
    [EAFNOSUPPORT]	= TARGET_EAFNOSUPPORT,
    [EADDRINUSE]	= TARGET_EADDRINUSE,
    [EADDRNOTAVAIL]	= TARGET_EADDRNOTAVAIL,
    [ENETDOWN]		= TARGET_ENETDOWN,
    [ENETUNREACH]	= TARGET_ENETUNREACH,
    [ENETRESET]		= TARGET_ENETRESET,
    [ECONNABORTED]	= TARGET_ECONNABORTED,
    [ECONNRESET]	= TARGET_ECONNRESET,
    [ENOBUFS]		= TARGET_ENOBUFS,
    [EISCONN]		= TARGET_EISCONN,
    [ENOTCONN]		= TARGET_ENOTCONN,
    [EUCLEAN]		= TARGET_EUCLEAN,
    [ENOTNAM]		= TARGET_ENOTNAM,
    [ENAVAIL]		= TARGET_ENAVAIL,
    [EISNAM]		= TARGET_EISNAM,
    [EREMOTEIO]		= TARGET_EREMOTEIO,
    [ESHUTDOWN]		= TARGET_ESHUTDOWN,
    [ETOOMANYREFS]	= TARGET_ETOOMANYREFS,
    [ETIMEDOUT]		= TARGET_ETIMEDOUT,
    [ECONNREFUSED]	= TARGET_ECONNREFUSED,
    [EHOSTDOWN]		= TARGET_EHOSTDOWN,
    [EHOSTUNREACH]	= TARGET_EHOSTUNREACH,
    [EALREADY]		= TARGET_EALREADY,
    [EINPROGRESS]	= TARGET_EINPROGRESS,
    [ESTALE]		= TARGET_ESTALE,
    [ECANCELED]		= TARGET_ECANCELED,
    [ENOMEDIUM]		= TARGET_ENOMEDIUM,
    [EMEDIUMTYPE]	= TARGET_EMEDIUMTYPE,
T
ths 已提交
353
#ifdef ENOKEY
354
    [ENOKEY]		= TARGET_ENOKEY,
T
ths 已提交
355 356
#endif
#ifdef EKEYEXPIRED
357
    [EKEYEXPIRED]	= TARGET_EKEYEXPIRED,
T
ths 已提交
358 359
#endif
#ifdef EKEYREVOKED
360
    [EKEYREVOKED]	= TARGET_EKEYREVOKED,
T
ths 已提交
361 362
#endif
#ifdef EKEYREJECTED
363
    [EKEYREJECTED]	= TARGET_EKEYREJECTED,
T
ths 已提交
364 365
#endif
#ifdef EOWNERDEAD
366
    [EOWNERDEAD]	= TARGET_EOWNERDEAD,
T
ths 已提交
367 368
#endif
#ifdef ENOTRECOVERABLE
369
    [ENOTRECOVERABLE]	= TARGET_ENOTRECOVERABLE,
T
ths 已提交
370
#endif
371
};
372 373 374 375 376 377 378 379

static inline int host_to_target_errno(int err)
{
    if(host_to_target_errno_table[err])
        return host_to_target_errno_table[err];
    return err;
}

380 381 382 383 384 385 386
static inline int target_to_host_errno(int err)
{
    if (target_to_host_errno_table[err])
        return target_to_host_errno_table[err];
    return err;
}

387
static inline abi_long get_errno(abi_long ret)
388 389
{
    if (ret == -1)
390
        return -host_to_target_errno(errno);
391 392 393 394
    else
        return ret;
}

395
static inline int is_error(abi_long ret)
396
{
397
    return (abi_ulong)ret >= (abi_ulong)(-4096);
398 399
}

400 401 402 403 404
char *target_strerror(int err)
{
    return strerror(target_to_host_errno(err));
}

405 406
static abi_ulong target_brk;
static abi_ulong target_original_brk;
407

408
void target_set_brk(abi_ulong new_brk)
409
{
410
    target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
411 412
}

413
/* do_brk() must return target values and target errnos. */
414
abi_long do_brk(abi_ulong new_brk)
415
{
416 417
    abi_ulong brk_page;
    abi_long mapped_addr;
418 419 420
    int	new_alloc_size;

    if (!new_brk)
421
        return target_brk;
422
    if (new_brk < target_original_brk)
423
        return -TARGET_ENOMEM;
424

425
    brk_page = HOST_PAGE_ALIGN(target_brk);
426 427 428 429

    /* If the new brk is less than this, set it and we're done... */
    if (new_brk < brk_page) {
	target_brk = new_brk;
430
    	return target_brk;
431 432 433
    }

    /* We need to allocate more memory after the brk... */
B
bellard 已提交
434
    new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
435
    mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
B
bellard 已提交
436 437
                                        PROT_READ|PROT_WRITE,
                                        MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
438 439 440 441
    if (is_error(mapped_addr)) {
	return mapped_addr;
    } else {
	target_brk = new_brk;
442
    	return target_brk;
443 444 445
    }
}

446
static inline fd_set *target_to_host_fds(fd_set *fds,
447
                                         abi_long *target_fds, int n)
448
{
B
bellard 已提交
449
#if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN)
450 451 452 453 454 455
    return (fd_set *)target_fds;
#else
    int i, b;
    if (target_fds) {
        FD_ZERO(fds);
        for(i = 0;i < n; i++) {
456 457
            b = (tswapl(target_fds[i / TARGET_ABI_BITS]) >>
                 (i & (TARGET_ABI_BITS - 1))) & 1;
458 459 460 461 462 463 464 465 466 467
            if (b)
                FD_SET(i, fds);
        }
        return fds;
    } else {
        return NULL;
    }
#endif
}

468
static inline void host_to_target_fds(abi_long *target_fds,
469 470
                                      fd_set *fds, int n)
{
B
bellard 已提交
471
#if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN)
472 473 474
    /* nothing to do */
#else
    int i, nw, j, k;
475
    abi_long v;
476 477

    if (target_fds) {
478
        nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
479 480 481
        k = 0;
        for(i = 0;i < nw; i++) {
            v = 0;
482
            for(j = 0; j < TARGET_ABI_BITS; j++) {
483 484 485 486 487 488 489 490 491
                v |= ((FD_ISSET(k, fds) != 0) << j);
                k++;
            }
            target_fds[i] = tswapl(v);
        }
    }
#endif
}

B
bellard 已提交
492 493 494 495 496 497
#if defined(__alpha__)
#define HOST_HZ 1024
#else
#define HOST_HZ 100
#endif

498
static inline abi_long host_to_target_clock_t(long ticks)
B
bellard 已提交
499 500 501 502 503 504 505 506
{
#if HOST_HZ == TARGET_HZ
    return ticks;
#else
    return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
#endif
}

507 508
static inline abi_long host_to_target_rusage(abi_ulong target_addr,
                                             const struct rusage *rusage)
B
bellard 已提交
509
{
510 511
    struct target_rusage *target_rusage;

512 513
    if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
        return -TARGET_EFAULT;
B
bellard 已提交
514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
    target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
    target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
    target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
    target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec);
    target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss);
    target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss);
    target_rusage->ru_idrss = tswapl(rusage->ru_idrss);
    target_rusage->ru_isrss = tswapl(rusage->ru_isrss);
    target_rusage->ru_minflt = tswapl(rusage->ru_minflt);
    target_rusage->ru_majflt = tswapl(rusage->ru_majflt);
    target_rusage->ru_nswap = tswapl(rusage->ru_nswap);
    target_rusage->ru_inblock = tswapl(rusage->ru_inblock);
    target_rusage->ru_oublock = tswapl(rusage->ru_oublock);
    target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd);
    target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv);
    target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals);
    target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
    target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
532
    unlock_user_struct(target_rusage, target_addr, 1);
533 534

    return 0;
B
bellard 已提交
535 536
}

537 538
static inline abi_long target_to_host_timeval(struct timeval *tv,
                                              abi_ulong target_addr)
539
{
540 541
    struct target_timeval *target_tv;

542 543
    if (!lock_user_struct(VERIFY_READ, target_tv, target_addr, 1))
        return -TARGET_EFAULT;
B
bellard 已提交
544 545
    tv->tv_sec = tswapl(target_tv->tv_sec);
    tv->tv_usec = tswapl(target_tv->tv_usec);
546
    unlock_user_struct(target_tv, target_addr, 0);
547 548

    return 0;
549 550
}

551 552
static inline abi_long host_to_target_timeval(abi_ulong target_addr,
                                              const struct timeval *tv)
553
{
554 555
    struct target_timeval *target_tv;

556 557
    if (!lock_user_struct(VERIFY_WRITE, target_tv, target_addr, 0))
        return -TARGET_EFAULT;
B
bellard 已提交
558 559
    target_tv->tv_sec = tswapl(tv->tv_sec);
    target_tv->tv_usec = tswapl(tv->tv_usec);
560
    unlock_user_struct(target_tv, target_addr, 1);
561 562

    return 0;
563 564 565
}


566
/* do_select() must return target values and target errnos. */
567 568 569
static abi_long do_select(int n,
                          abi_ulong rfd_p, abi_ulong wfd_p,
                          abi_ulong efd_p, abi_ulong target_tv)
570 571 572
{
    fd_set rfds, wfds, efds;
    fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
573
    abi_long *target_rfds, *target_wfds, *target_efds;
574
    struct timeval tv, *tv_ptr;
575
    abi_long ret;
576
    int ok;
577

578
    if (rfd_p) {
579 580 581 582 583
        target_rfds = lock_user(VERIFY_WRITE, rfd_p, sizeof(abi_long) * n, 1);
        if (!target_rfds) {
            ret = -TARGET_EFAULT;
            goto end;
        }
584 585 586 587 588 589
        rfds_ptr = target_to_host_fds(&rfds, target_rfds, n);
    } else {
        target_rfds = NULL;
        rfds_ptr = NULL;
    }
    if (wfd_p) {
590 591 592 593 594
        target_wfds = lock_user(VERIFY_WRITE, wfd_p, sizeof(abi_long) * n, 1);
        if (!target_wfds) {
            ret = -TARGET_EFAULT;
            goto end;
        }
595 596 597 598 599 600
        wfds_ptr = target_to_host_fds(&wfds, target_wfds, n);
    } else {
        target_wfds = NULL;
        wfds_ptr = NULL;
    }
    if (efd_p) {
601 602 603 604 605
        target_efds = lock_user(VERIFY_WRITE, efd_p, sizeof(abi_long) * n, 1);
        if (!target_efds) {
            ret = -TARGET_EFAULT;
            goto end;
        }
606 607 608 609 610
        efds_ptr = target_to_host_fds(&efds, target_efds, n);
    } else {
        target_efds = NULL;
        efds_ptr = NULL;
    }
611

612
    if (target_tv) {
B
bellard 已提交
613
        target_to_host_timeval(&tv, target_tv);
614 615 616 617 618
        tv_ptr = &tv;
    } else {
        tv_ptr = NULL;
    }
    ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
619 620 621
    ok = !is_error(ret);

    if (ok) {
622 623 624 625 626
        host_to_target_fds(target_rfds, rfds_ptr, n);
        host_to_target_fds(target_wfds, wfds_ptr, n);
        host_to_target_fds(target_efds, efds_ptr, n);

        if (target_tv) {
B
bellard 已提交
627
            host_to_target_timeval(target_tv, &tv);
628 629
        }
    }
630 631 632 633 634

end:
    unlock_user(target_rfds, rfd_p, ok ? sizeof(abi_long) * n : 0);
    unlock_user(target_wfds, wfd_p, ok ? sizeof(abi_long) * n : 0);
    unlock_user(target_efds, efd_p, ok ? sizeof(abi_long) * n : 0);
635

636 637 638
    return ret;
}

639 640 641
static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
                                               abi_ulong target_addr,
                                               socklen_t len)
B
bellard 已提交
642
{
643 644
    struct target_sockaddr *target_saddr;

645 646 647
    target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
    if (!target_saddr)
        return -TARGET_EFAULT;
648 649 650
    memcpy(addr, target_saddr, len);
    addr->sa_family = tswap16(target_saddr->sa_family);
    unlock_user(target_saddr, target_addr, 0);
651 652

    return 0;
B
bellard 已提交
653 654
}

655 656 657
static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
                                               struct sockaddr *addr,
                                               socklen_t len)
B
bellard 已提交
658
{
659 660
    struct target_sockaddr *target_saddr;

661 662 663
    target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
    if (!target_saddr)
        return -TARGET_EFAULT;
664 665 666
    memcpy(target_saddr, addr, len);
    target_saddr->sa_family = tswap16(addr->sa_family);
    unlock_user(target_saddr, target_addr, len);
667 668

    return 0;
B
bellard 已提交
669 670
}

671
/* ??? Should this also swap msgh->name?  */
672 673
static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
                                           struct target_msghdr *target_msgh)
B
bellard 已提交
674 675
{
    struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
676 677 678
    abi_long msg_controllen;
    abi_ulong target_cmsg_addr;
    struct target_cmsghdr *target_cmsg;
B
bellard 已提交
679
    socklen_t space = 0;
680 681 682 683 684 685 686 687
    
    msg_controllen = tswapl(target_msgh->msg_controllen);
    if (msg_controllen < sizeof (struct target_cmsghdr)) 
        goto the_end;
    target_cmsg_addr = tswapl(target_msgh->msg_control);
    target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
    if (!target_cmsg)
        return -TARGET_EFAULT;
B
bellard 已提交
688 689 690 691 692

    while (cmsg && target_cmsg) {
        void *data = CMSG_DATA(cmsg);
        void *target_data = TARGET_CMSG_DATA(target_cmsg);

693
        int len = tswapl(target_cmsg->cmsg_len)
B
bellard 已提交
694 695 696 697 698
                  - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));

        space += CMSG_SPACE(len);
        if (space > msgh->msg_controllen) {
            space -= CMSG_SPACE(len);
B
bellard 已提交
699
            gemu_log("Host cmsg overflow\n");
B
bellard 已提交
700 701 702 703 704 705 706
            break;
        }

        cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
        cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
        cmsg->cmsg_len = CMSG_LEN(len);

707
        if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
B
bellard 已提交
708 709 710 711 712 713 714 715 716 717 718 719 720 721
            gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
            memcpy(data, target_data, len);
        } else {
            int *fd = (int *)data;
            int *target_fd = (int *)target_data;
            int i, numfds = len / sizeof(int);

            for (i = 0; i < numfds; i++)
                fd[i] = tswap32(target_fd[i]);
        }

        cmsg = CMSG_NXTHDR(msgh, cmsg);
        target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
    }
722 723
    unlock_user(target_cmsg, target_cmsg_addr, 0);
 the_end:
B
bellard 已提交
724
    msgh->msg_controllen = space;
725
    return 0;
B
bellard 已提交
726 727
}

728
/* ??? Should this also swap msgh->name?  */
729 730
static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
                                           struct msghdr *msgh)
B
bellard 已提交
731 732
{
    struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
733 734 735
    abi_long msg_controllen;
    abi_ulong target_cmsg_addr;
    struct target_cmsghdr *target_cmsg;
B
bellard 已提交
736 737
    socklen_t space = 0;

738 739 740 741 742 743 744 745
    msg_controllen = tswapl(target_msgh->msg_controllen);
    if (msg_controllen < sizeof (struct target_cmsghdr)) 
        goto the_end;
    target_cmsg_addr = tswapl(target_msgh->msg_control);
    target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
    if (!target_cmsg)
        return -TARGET_EFAULT;

B
bellard 已提交
746 747 748 749 750 751 752
    while (cmsg && target_cmsg) {
        void *data = CMSG_DATA(cmsg);
        void *target_data = TARGET_CMSG_DATA(target_cmsg);

        int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));

        space += TARGET_CMSG_SPACE(len);
753
        if (space > msg_controllen) {
B
bellard 已提交
754
            space -= TARGET_CMSG_SPACE(len);
B
bellard 已提交
755
            gemu_log("Target cmsg overflow\n");
B
bellard 已提交
756 757 758 759 760 761 762
            break;
        }

        target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
        target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
        target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));

763
        if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
B
bellard 已提交
764 765 766 767 768 769 770 771 772 773 774 775 776 777
            gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
            memcpy(target_data, data, len);
        } else {
            int *fd = (int *)data;
            int *target_fd = (int *)target_data;
            int i, numfds = len / sizeof(int);

            for (i = 0; i < numfds; i++)
                target_fd[i] = tswap32(fd[i]);
        }

        cmsg = CMSG_NXTHDR(msgh, cmsg);
        target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
    }
778 779 780 781
    unlock_user(target_cmsg, target_cmsg_addr, space);
 the_end:
    target_msgh->msg_controllen = tswapl(space);
    return 0;
B
bellard 已提交
782 783
}

784
/* do_setsockopt() Must return target values and target errnos. */
785 786
static abi_long do_setsockopt(int sockfd, int level, int optname,
                              abi_ulong optval, socklen_t optlen)
B
bellard 已提交
787
{
788
    abi_long ret;
789
    int val;
790

791 792
    switch(level) {
    case SOL_TCP:
B
bellard 已提交
793 794
        /* TCP options all take an 'int' value.  */
        if (optlen < sizeof(uint32_t))
795
            return -TARGET_EINVAL;
796

797
        val = tget32(optval);
798 799 800 801
        ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
        break;
    case SOL_IP:
        switch(optname) {
B
bellard 已提交
802 803
        case IP_TOS:
        case IP_TTL:
804
        case IP_HDRINCL:
B
bellard 已提交
805 806 807 808 809 810 811 812 813 814 815 816
        case IP_ROUTER_ALERT:
        case IP_RECVOPTS:
        case IP_RETOPTS:
        case IP_PKTINFO:
        case IP_MTU_DISCOVER:
        case IP_RECVERR:
        case IP_RECVTOS:
#ifdef IP_FREEBIND
        case IP_FREEBIND:
#endif
        case IP_MULTICAST_TTL:
        case IP_MULTICAST_LOOP:
817 818
            val = 0;
            if (optlen >= sizeof(uint32_t)) {
819
                val = tget32(optval);
820
            } else if (optlen >= 1) {
821
                val = tget8(optval);
822 823 824 825 826 827 828
            }
            ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
            break;
        default:
            goto unimplemented;
        }
        break;
829
    case TARGET_SOL_SOCKET:
830 831
        switch (optname) {
            /* Options with 'int' argument.  */
832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867
        case TARGET_SO_DEBUG:
		optname = SO_DEBUG;
		break;
        case TARGET_SO_REUSEADDR:
		optname = SO_REUSEADDR;
		break;
        case TARGET_SO_TYPE:
		optname = SO_TYPE;
		break;
        case TARGET_SO_ERROR:
		optname = SO_ERROR;
		break;
        case TARGET_SO_DONTROUTE:
		optname = SO_DONTROUTE;
		break;
        case TARGET_SO_BROADCAST:
		optname = SO_BROADCAST;
		break;
        case TARGET_SO_SNDBUF:
		optname = SO_SNDBUF;
		break;
        case TARGET_SO_RCVBUF:
		optname = SO_RCVBUF;
		break;
        case TARGET_SO_KEEPALIVE:
		optname = SO_KEEPALIVE;
		break;
        case TARGET_SO_OOBINLINE:
		optname = SO_OOBINLINE;
		break;
        case TARGET_SO_NO_CHECK:
		optname = SO_NO_CHECK;
		break;
        case TARGET_SO_PRIORITY:
		optname = SO_PRIORITY;
		break;
B
bellard 已提交
868
#ifdef SO_BSDCOMPAT
869 870 871
        case TARGET_SO_BSDCOMPAT:
		optname = SO_BSDCOMPAT;
		break;
B
bellard 已提交
872
#endif
873 874 875 876 877 878 879 880 881 882 883 884 885 886 887
        case TARGET_SO_PASSCRED:
		optname = SO_PASSCRED;
		break;
        case TARGET_SO_TIMESTAMP:
		optname = SO_TIMESTAMP;
		break;
        case TARGET_SO_RCVLOWAT:
		optname = SO_RCVLOWAT;
		break;
        case TARGET_SO_RCVTIMEO:
		optname = SO_RCVTIMEO;
		break;
        case TARGET_SO_SNDTIMEO:
		optname = SO_SNDTIMEO;
		break;
888 889 890 891
            break;
        default:
            goto unimplemented;
        }
892
	if (optlen < sizeof(uint32_t))
893
	return -TARGET_EINVAL;
894 895 896

	val = tget32(optval);
	ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
897
        break;
B
bellard 已提交
898
    default:
899 900
    unimplemented:
        gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
901
        ret = -TARGET_ENOSYS;
B
bellard 已提交
902
    }
903
    return ret;
B
bellard 已提交
904 905
}

906
/* do_getsockopt() Must return target values and target errnos. */
907 908
static abi_long do_getsockopt(int sockfd, int level, int optname,
                              abi_ulong optval, abi_ulong optlen)
B
bellard 已提交
909
{
910
    abi_long ret;
911
    int len, lv, val;
912 913

    switch(level) {
914 915
    case TARGET_SOL_SOCKET:
    	level = SOL_SOCKET;
916
	switch (optname) {
917 918 919 920 921
	case TARGET_SO_LINGER:
	case TARGET_SO_RCVTIMEO:
	case TARGET_SO_SNDTIMEO:
	case TARGET_SO_PEERCRED:
	case TARGET_SO_PEERNAME:
922 923 924
	    /* These don't just return a single integer */
	    goto unimplemented;
        default:
B
bellard 已提交
925 926 927 928 929 930
            goto int_case;
        }
        break;
    case SOL_TCP:
        /* TCP options all take an 'int' value.  */
    int_case:
931
        len = tget32(optlen);
B
bellard 已提交
932
        if (len < 0)
933
            return -TARGET_EINVAL;
B
bellard 已提交
934 935 936 937 938 939 940
        lv = sizeof(int);
        ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
        if (ret < 0)
            return ret;
        val = tswap32(val);
        if (len > lv)
            len = lv;
941 942 943 944 945
        if (len == 4)
            tput32(optval, val);
        else
            tput8(optval, val);
        tput32(optlen, len);
B
bellard 已提交
946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963
        break;
    case SOL_IP:
        switch(optname) {
        case IP_TOS:
        case IP_TTL:
        case IP_HDRINCL:
        case IP_ROUTER_ALERT:
        case IP_RECVOPTS:
        case IP_RETOPTS:
        case IP_PKTINFO:
        case IP_MTU_DISCOVER:
        case IP_RECVERR:
        case IP_RECVTOS:
#ifdef IP_FREEBIND
        case IP_FREEBIND:
#endif
        case IP_MULTICAST_TTL:
        case IP_MULTICAST_LOOP:
964
            len = tget32(optlen);
965
            if (len < 0)
966
                return -TARGET_EINVAL;
967 968 969 970
            lv = sizeof(int);
            ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
            if (ret < 0)
                return ret;
B
bellard 已提交
971 972
            if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
                len = 1;
973 974
                tput32(optlen, len);
                tput8(optval, val);
B
bellard 已提交
975 976 977
            } else {
                if (len > sizeof(int))
                    len = sizeof(int);
978 979
                tput32(optlen, len);
                tput32(optval, val);
B
bellard 已提交
980
            }
981
            break;
B
bellard 已提交
982 983
        default:
            goto unimplemented;
984 985 986 987 988 989
        }
        break;
    default:
    unimplemented:
        gemu_log("getsockopt level=%d optname=%d not yet supported\n",
                 level, optname);
990
        ret = -TARGET_ENOSYS;
991 992 993
        break;
    }
    return ret;
B
bellard 已提交
994 995
}

996 997 998 999 1000 1001
/* FIXME
 * lock_iovec()/unlock_iovec() have a return code of 0 for success where
 * other lock functions have a return code of 0 for failure.
 */
static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
                           int count, int copy)
1002 1003
{
    struct target_iovec *target_vec;
1004
    abi_ulong base;
1005
    int i, j;
1006

1007 1008 1009
    target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
    if (!target_vec)
        return -TARGET_EFAULT;
1010 1011 1012
    for(i = 0;i < count; i++) {
        base = tswapl(target_vec[i].iov_base);
        vec[i].iov_len = tswapl(target_vec[i].iov_len);
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
        vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
	if (!vec[i].iov_base) 
            goto fail;
    }
    unlock_user (target_vec, target_addr, 0);
    return 0;
 fail:
    /* failure - unwind locks */
    for (j = 0; j < i; j++) {
        base = tswapl(target_vec[j].iov_base);
        unlock_user(vec[j].iov_base, base, 0);
1024 1025
    }
    unlock_user (target_vec, target_addr, 0);
1026
    return -TARGET_EFAULT;
1027 1028
}

1029 1030
static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
                             int count, int copy)
1031 1032
{
    struct target_iovec *target_vec;
1033
    abi_ulong base;
1034 1035
    int i;

1036 1037 1038
    target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
    if (!target_vec)
        return -TARGET_EFAULT;
1039 1040 1041 1042 1043
    for(i = 0;i < count; i++) {
        base = tswapl(target_vec[i].iov_base);
        unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
    }
    unlock_user (target_vec, target_addr, 0);
1044 1045

    return 0;
1046 1047
}

1048
/* do_socket() Must return target values and target errnos. */
1049
static abi_long do_socket(int domain, int type, int protocol)
1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072
{
#if defined(TARGET_MIPS)
    switch(type) {
    case TARGET_SOCK_DGRAM:
        type = SOCK_DGRAM;
        break;
    case TARGET_SOCK_STREAM:
        type = SOCK_STREAM;
        break;
    case TARGET_SOCK_RAW:
        type = SOCK_RAW;
        break;
    case TARGET_SOCK_RDM:
        type = SOCK_RDM;
        break;
    case TARGET_SOCK_SEQPACKET:
        type = SOCK_SEQPACKET;
        break;
    case TARGET_SOCK_PACKET:
        type = SOCK_PACKET;
        break;
    }
#endif
1073 1074
    if (domain == PF_NETLINK)
        return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
1075 1076 1077
    return get_errno(socket(domain, type, protocol));
}

1078
/* do_bind() Must return target values and target errnos. */
1079 1080
static abi_long do_bind(int sockfd, abi_ulong target_addr,
                        socklen_t addrlen)
1081 1082
{
    void *addr = alloca(addrlen);
1083

1084 1085 1086 1087
    target_to_host_sockaddr(addr, target_addr, addrlen);
    return get_errno(bind(sockfd, addr, addrlen));
}

1088
/* do_connect() Must return target values and target errnos. */
1089 1090
static abi_long do_connect(int sockfd, abi_ulong target_addr,
                           socklen_t addrlen)
1091 1092
{
    void *addr = alloca(addrlen);
1093

1094 1095 1096 1097
    target_to_host_sockaddr(addr, target_addr, addrlen);
    return get_errno(connect(sockfd, addr, addrlen));
}

1098
/* do_sendrecvmsg() Must return target values and target errnos. */
1099 1100
static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
                               int flags, int send)
1101
{
1102
    abi_long ret;
1103 1104 1105 1106
    struct target_msghdr *msgp;
    struct msghdr msg;
    int count;
    struct iovec *vec;
1107
    abi_ulong target_vec;
1108

1109 1110 1111 1112 1113 1114
    /* FIXME */
    if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
                          msgp,
                          target_msg,
                          send ? 1 : 0))
        return -TARGET_EFAULT;
1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126
    if (msgp->msg_name) {
        msg.msg_namelen = tswap32(msgp->msg_namelen);
        msg.msg_name = alloca(msg.msg_namelen);
        target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
                                msg.msg_namelen);
    } else {
        msg.msg_name = NULL;
        msg.msg_namelen = 0;
    }
    msg.msg_controllen = 2 * tswapl(msgp->msg_controllen);
    msg.msg_control = alloca(msg.msg_controllen);
    msg.msg_flags = tswap32(msgp->msg_flags);
1127

1128 1129 1130
    count = tswapl(msgp->msg_iovlen);
    vec = alloca(count * sizeof(struct iovec));
    target_vec = tswapl(msgp->msg_iov);
1131
    lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
1132 1133
    msg.msg_iovlen = count;
    msg.msg_iov = vec;
1134

1135
    if (send) {
1136 1137 1138
        ret = target_to_host_cmsg(&msg, msgp);
        if (ret == 0)
            ret = get_errno(sendmsg(fd, &msg, flags));
1139 1140 1141
    } else {
        ret = get_errno(recvmsg(fd, &msg, flags));
        if (!is_error(ret))
1142
            ret = host_to_target_cmsg(msgp, &msg);
1143 1144
    }
    unlock_iovec(vec, target_vec, count, !send);
1145
    unlock_user_struct(msgp, target_msg, send ? 0 : 1);
1146 1147 1148
    return ret;
}

1149
/* do_accept() Must return target values and target errnos. */
1150 1151
static abi_long do_accept(int fd, abi_ulong target_addr,
                          abi_ulong target_addrlen)
P
pbrook 已提交
1152 1153
{
    socklen_t addrlen = tget32(target_addrlen);
T
ths 已提交
1154
    void *addr = alloca(addrlen);
1155
    abi_long ret;
P
pbrook 已提交
1156 1157 1158 1159 1160 1161 1162 1163 1164

    ret = get_errno(accept(fd, addr, &addrlen));
    if (!is_error(ret)) {
        host_to_target_sockaddr(target_addr, addr, addrlen);
        tput32(target_addrlen, addrlen);
    }
    return ret;
}

1165
/* do_getpeername() Must return target values and target errnos. */
1166 1167
static abi_long do_getpeername(int fd, abi_ulong target_addr,
                               abi_ulong target_addrlen)
P
pbrook 已提交
1168 1169
{
    socklen_t addrlen = tget32(target_addrlen);
1170
    void *addr = alloca(addrlen);
1171
    abi_long ret;
P
pbrook 已提交
1172 1173 1174 1175 1176 1177 1178 1179 1180

    ret = get_errno(getpeername(fd, addr, &addrlen));
    if (!is_error(ret)) {
        host_to_target_sockaddr(target_addr, addr, addrlen);
        tput32(target_addrlen, addrlen);
    }
    return ret;
}

1181
/* do_getsockname() Must return target values and target errnos. */
1182 1183
static abi_long do_getsockname(int fd, abi_ulong target_addr,
                               abi_ulong target_addrlen)
P
pbrook 已提交
1184 1185
{
    socklen_t addrlen = tget32(target_addrlen);
1186
    void *addr = alloca(addrlen);
1187
    abi_long ret;
P
pbrook 已提交
1188 1189 1190 1191 1192 1193 1194 1195 1196

    ret = get_errno(getsockname(fd, addr, &addrlen));
    if (!is_error(ret)) {
        host_to_target_sockaddr(target_addr, addr, addrlen);
        tput32(target_addrlen, addrlen);
    }
    return ret;
}

1197
/* do_socketpair() Must return target values and target errnos. */
1198 1199
static abi_long do_socketpair(int domain, int type, int protocol,
                              abi_ulong target_tab)
P
pbrook 已提交
1200 1201
{
    int tab[2];
1202
    abi_long ret;
P
pbrook 已提交
1203 1204 1205 1206 1207 1208 1209 1210 1211

    ret = get_errno(socketpair(domain, type, protocol, tab));
    if (!is_error(ret)) {
        tput32(target_tab, tab[0]);
        tput32(target_tab + 4, tab[1]);
    }
    return ret;
}

1212
/* do_sendto() Must return target values and target errnos. */
1213 1214
static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
                          abi_ulong target_addr, socklen_t addrlen)
P
pbrook 已提交
1215 1216 1217
{
    void *addr;
    void *host_msg;
1218
    abi_long ret;
P
pbrook 已提交
1219

1220 1221 1222
    host_msg = lock_user(VERIFY_READ, msg, len, 1);
    if (!host_msg)
        return -TARGET_EFAULT;
P
pbrook 已提交
1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233
    if (target_addr) {
        addr = alloca(addrlen);
        target_to_host_sockaddr(addr, target_addr, addrlen);
        ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
    } else {
        ret = get_errno(send(fd, host_msg, len, flags));
    }
    unlock_user(host_msg, msg, 0);
    return ret;
}

1234
/* do_recvfrom() Must return target values and target errnos. */
1235 1236 1237
static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
                            abi_ulong target_addr,
                            abi_ulong target_addrlen)
P
pbrook 已提交
1238 1239 1240 1241
{
    socklen_t addrlen;
    void *addr;
    void *host_msg;
1242
    abi_long ret;
P
pbrook 已提交
1243

1244 1245 1246
    host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
    if (!host_msg)
        return -TARGET_EFAULT;
P
pbrook 已提交
1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266
    if (target_addr) {
        addrlen = tget32(target_addrlen);
        addr = alloca(addrlen);
        ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
    } else {
        addr = NULL; /* To keep compiler quiet.  */
        ret = get_errno(recv(fd, host_msg, len, flags));
    }
    if (!is_error(ret)) {
        if (target_addr) {
            host_to_target_sockaddr(target_addr, addr, addrlen);
            tput32(target_addrlen, addrlen);
        }
        unlock_user(host_msg, msg, len);
    } else {
        unlock_user(host_msg, msg, 0);
    }
    return ret;
}

1267
#ifdef TARGET_NR_socketcall
1268
/* do_socketcall() Must return target values and target errnos. */
1269
static abi_long do_socketcall(int num, abi_ulong vptr)
1270
{
1271 1272
    abi_long ret;
    const int n = sizeof(abi_ulong);
1273 1274 1275

    switch(num) {
    case SOCKOP_socket:
B
bellard 已提交
1276
	{
1277 1278 1279
            int domain = tgetl(vptr);
            int type = tgetl(vptr + n);
            int protocol = tgetl(vptr + 2 * n);
1280
            ret = do_socket(domain, type, protocol);
B
bellard 已提交
1281
	}
1282 1283
        break;
    case SOCKOP_bind:
B
bellard 已提交
1284
	{
1285
            int sockfd = tgetl(vptr);
1286
            abi_ulong target_addr = tgetl(vptr + n);
1287
            socklen_t addrlen = tgetl(vptr + 2 * n);
1288
            ret = do_bind(sockfd, target_addr, addrlen);
B
bellard 已提交
1289
        }
1290 1291
        break;
    case SOCKOP_connect:
B
bellard 已提交
1292
        {
1293
            int sockfd = tgetl(vptr);
1294
            abi_ulong target_addr = tgetl(vptr + n);
1295
            socklen_t addrlen = tgetl(vptr + 2 * n);
1296
            ret = do_connect(sockfd, target_addr, addrlen);
B
bellard 已提交
1297
        }
1298 1299
        break;
    case SOCKOP_listen:
B
bellard 已提交
1300
        {
1301 1302
            int sockfd = tgetl(vptr);
            int backlog = tgetl(vptr + n);
B
bellard 已提交
1303 1304
            ret = get_errno(listen(sockfd, backlog));
        }
1305 1306 1307
        break;
    case SOCKOP_accept:
        {
1308
            int sockfd = tgetl(vptr);
1309 1310
            abi_ulong target_addr = tgetl(vptr + n);
            abi_ulong target_addrlen = tgetl(vptr + 2 * n);
P
pbrook 已提交
1311
            ret = do_accept(sockfd, target_addr, target_addrlen);
1312 1313 1314 1315
        }
        break;
    case SOCKOP_getsockname:
        {
1316
            int sockfd = tgetl(vptr);
1317 1318
            abi_ulong target_addr = tgetl(vptr + n);
            abi_ulong target_addrlen = tgetl(vptr + 2 * n);
P
pbrook 已提交
1319
            ret = do_getsockname(sockfd, target_addr, target_addrlen);
1320 1321 1322 1323
        }
        break;
    case SOCKOP_getpeername:
        {
1324
            int sockfd = tgetl(vptr);
1325 1326
            abi_ulong target_addr = tgetl(vptr + n);
            abi_ulong target_addrlen = tgetl(vptr + 2 * n);
P
pbrook 已提交
1327
            ret = do_getpeername(sockfd, target_addr, target_addrlen);
1328 1329 1330 1331
        }
        break;
    case SOCKOP_socketpair:
        {
1332 1333 1334
            int domain = tgetl(vptr);
            int type = tgetl(vptr + n);
            int protocol = tgetl(vptr + 2 * n);
1335
            abi_ulong tab = tgetl(vptr + 3 * n);
P
pbrook 已提交
1336
            ret = do_socketpair(domain, type, protocol, tab);
1337 1338 1339
        }
        break;
    case SOCKOP_send:
B
bellard 已提交
1340
        {
1341
            int sockfd = tgetl(vptr);
1342
            abi_ulong msg = tgetl(vptr + n);
1343 1344
            size_t len = tgetl(vptr + 2 * n);
            int flags = tgetl(vptr + 3 * n);
P
pbrook 已提交
1345
            ret = do_sendto(sockfd, msg, len, flags, 0, 0);
B
bellard 已提交
1346
        }
1347 1348
        break;
    case SOCKOP_recv:
B
bellard 已提交
1349
        {
1350
            int sockfd = tgetl(vptr);
1351
            abi_ulong msg = tgetl(vptr + n);
1352 1353
            size_t len = tgetl(vptr + 2 * n);
            int flags = tgetl(vptr + 3 * n);
P
pbrook 已提交
1354
            ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
B
bellard 已提交
1355
        }
1356 1357
        break;
    case SOCKOP_sendto:
B
bellard 已提交
1358
        {
1359
            int sockfd = tgetl(vptr);
1360
            abi_ulong msg = tgetl(vptr + n);
1361 1362
            size_t len = tgetl(vptr + 2 * n);
            int flags = tgetl(vptr + 3 * n);
1363
            abi_ulong addr = tgetl(vptr + 4 * n);
1364
            socklen_t addrlen = tgetl(vptr + 5 * n);
P
pbrook 已提交
1365
            ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
B
bellard 已提交
1366
        }
1367 1368 1369
        break;
    case SOCKOP_recvfrom:
        {
1370
            int sockfd = tgetl(vptr);
1371
            abi_ulong msg = tgetl(vptr + n);
1372 1373
            size_t len = tgetl(vptr + 2 * n);
            int flags = tgetl(vptr + 3 * n);
1374 1375
            abi_ulong addr = tgetl(vptr + 4 * n);
            abi_ulong addrlen = tgetl(vptr + 5 * n);
P
pbrook 已提交
1376
            ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
1377 1378 1379
        }
        break;
    case SOCKOP_shutdown:
B
bellard 已提交
1380
        {
1381 1382
            int sockfd = tgetl(vptr);
            int how = tgetl(vptr + n);
B
bellard 已提交
1383 1384 1385

            ret = get_errno(shutdown(sockfd, how));
        }
1386 1387 1388
        break;
    case SOCKOP_sendmsg:
    case SOCKOP_recvmsg:
B
bellard 已提交
1389 1390
        {
            int fd;
1391
            abi_ulong target_msg;
1392
            int flags;
B
bellard 已提交
1393

1394
            fd = tgetl(vptr);
1395
            target_msg = tgetl(vptr + n);
1396
            flags = tgetl(vptr + 2 * n);
1397

1398
            ret = do_sendrecvmsg(fd, target_msg, flags,
1399
                                 (num == SOCKOP_sendmsg));
B
bellard 已提交
1400 1401
        }
        break;
1402
    case SOCKOP_setsockopt:
B
bellard 已提交
1403
        {
1404 1405 1406
            int sockfd = tgetl(vptr);
            int level = tgetl(vptr + n);
            int optname = tgetl(vptr + 2 * n);
1407
            abi_ulong optval = tgetl(vptr + 3 * n);
1408
            socklen_t optlen = tgetl(vptr + 4 * n);
B
bellard 已提交
1409 1410 1411 1412

            ret = do_setsockopt(sockfd, level, optname, optval, optlen);
        }
        break;
1413
    case SOCKOP_getsockopt:
B
bellard 已提交
1414
        {
1415 1416 1417
            int sockfd = tgetl(vptr);
            int level = tgetl(vptr + n);
            int optname = tgetl(vptr + 2 * n);
1418 1419
            abi_ulong optval = tgetl(vptr + 3 * n);
            abi_ulong poptlen = tgetl(vptr + 4 * n);
B
bellard 已提交
1420

1421
            ret = do_getsockopt(sockfd, level, optname, optval, poptlen);
B
bellard 已提交
1422 1423
        }
        break;
1424 1425
    default:
        gemu_log("Unsupported socketcall: %d\n", num);
1426
        ret = -TARGET_ENOSYS;
1427 1428 1429 1430
        break;
    }
    return ret;
}
1431
#endif
1432

1433
#ifdef TARGET_NR_ipc
1434 1435 1436
#define N_SHM_REGIONS	32

static struct shm_region {
1437 1438
    abi_ulong	start;
    abi_ulong	size;
1439 1440
} shm_regions[N_SHM_REGIONS];

1441 1442
struct target_ipc_perm
{
1443 1444 1445 1446 1447
    abi_long __key;
    abi_ulong uid;
    abi_ulong gid;
    abi_ulong cuid;
    abi_ulong cgid;
1448 1449 1450 1451
    unsigned short int mode;
    unsigned short int __pad1;
    unsigned short int __seq;
    unsigned short int __pad2;
1452 1453
    abi_ulong __unused1;
    abi_ulong __unused2;
1454 1455 1456 1457 1458
};

struct target_semid_ds
{
  struct target_ipc_perm sem_perm;
1459 1460 1461 1462 1463 1464 1465
  abi_ulong sem_otime;
  abi_ulong __unused1;
  abi_ulong sem_ctime;
  abi_ulong __unused2;
  abi_ulong sem_nsems;
  abi_ulong __unused3;
  abi_ulong __unused4;
1466 1467
};

1468 1469
static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
                                               abi_ulong target_addr)
1470 1471 1472 1473
{
    struct target_ipc_perm *target_ip;
    struct target_semid_ds *target_sd;

1474 1475
    if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
        return -TARGET_EFAULT;
1476 1477 1478 1479 1480 1481 1482 1483
    target_ip=&(target_sd->sem_perm);
    host_ip->__key = tswapl(target_ip->__key);
    host_ip->uid = tswapl(target_ip->uid);
    host_ip->gid = tswapl(target_ip->gid);
    host_ip->cuid = tswapl(target_ip->cuid);
    host_ip->cgid = tswapl(target_ip->cgid);
    host_ip->mode = tswapl(target_ip->mode);
    unlock_user_struct(target_sd, target_addr, 0);
1484
    return 0;
1485 1486
}

1487 1488
static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
                                               struct ipc_perm *host_ip)
1489 1490 1491 1492
{
    struct target_ipc_perm *target_ip;
    struct target_semid_ds *target_sd;

1493 1494
    if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
        return -TARGET_EFAULT;
1495 1496 1497 1498 1499 1500 1501 1502
    target_ip = &(target_sd->sem_perm);
    target_ip->__key = tswapl(host_ip->__key);
    target_ip->uid = tswapl(host_ip->uid);
    target_ip->gid = tswapl(host_ip->gid);
    target_ip->cuid = tswapl(host_ip->cuid);
    target_ip->cgid = tswapl(host_ip->cgid);
    target_ip->mode = tswapl(host_ip->mode);
    unlock_user_struct(target_sd, target_addr, 1);
1503
    return 0;
1504 1505
}

1506 1507
static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
                                               abi_ulong target_addr)
1508 1509 1510
{
    struct target_semid_ds *target_sd;

1511 1512
    if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
        return -TARGET_EFAULT;
1513 1514 1515 1516 1517
    target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr);
    host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
    host_sd->sem_otime = tswapl(target_sd->sem_otime);
    host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
    unlock_user_struct(target_sd, target_addr, 0);
1518
    return 0;
1519 1520
}

1521 1522
static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
                                               struct semid_ds *host_sd)
1523 1524 1525
{
    struct target_semid_ds *target_sd;

1526 1527
    if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
        return -TARGET_EFAULT;
1528 1529 1530 1531 1532
    host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm));
    target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
    target_sd->sem_otime = tswapl(host_sd->sem_otime);
    target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
    unlock_user_struct(target_sd, target_addr, 1);
1533
    return 0;
1534 1535
}

1536 1537
union semun {
	int val;
1538
	struct semid_ds *buf;
1539 1540 1541
	unsigned short *array;
};

1542 1543
union target_semun {
	int val;
1544
	abi_long buf;
1545 1546 1547
	unsigned short int *array;
};

1548 1549 1550 1551
static inline abi_long target_to_host_semun(int cmd,
                                            union semun *host_su,
                                            abi_ulong target_addr,
                                            struct semid_ds *ds)
1552 1553 1554 1555 1556 1557
{
    union target_semun *target_su;

    switch( cmd ) {
	case IPC_STAT:
	case IPC_SET:
1558 1559
           if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
               return -TARGET_EFAULT;
1560 1561 1562 1563 1564 1565
	   target_to_host_semid_ds(ds,target_su->buf);
	   host_su->buf = ds;
           unlock_user_struct(target_su, target_addr, 0);
	   break;
	case GETVAL:
	case SETVAL:
1566 1567
           if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
               return -TARGET_EFAULT;
1568 1569 1570 1571 1572
	   host_su->val = tswapl(target_su->val);
           unlock_user_struct(target_su, target_addr, 0);
	   break;
	case GETALL:
	case SETALL:
1573 1574
           if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
               return -TARGET_EFAULT;
1575 1576 1577 1578 1579 1580
	   *host_su->array = tswap16(*target_su->array);
           unlock_user_struct(target_su, target_addr, 0);
	   break;
	default:
           gemu_log("semun operation not fully supported: %d\n", (int)cmd);
    }
1581
    return 0;
1582 1583
}

1584 1585 1586 1587
static inline abi_long host_to_target_semun(int cmd,
                                            abi_ulong target_addr,
                                            union semun *host_su,
                                            struct semid_ds *ds)
1588 1589 1590 1591 1592 1593
{
    union target_semun *target_su;

    switch( cmd ) {
	case IPC_STAT:
	case IPC_SET:
1594 1595
           if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
               return -TARGET_EFAULT;
1596 1597 1598 1599 1600
	   host_to_target_semid_ds(target_su->buf,ds);
           unlock_user_struct(target_su, target_addr, 1);
	   break;
	case GETVAL:
	case SETVAL:
1601 1602
           if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
               return -TARGET_EFAULT;
1603 1604 1605 1606 1607
	   target_su->val = tswapl(host_su->val);
           unlock_user_struct(target_su, target_addr, 1);
	   break;
	case GETALL:
	case SETALL:
1608 1609
           if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
               return -TARGET_EFAULT;
1610 1611 1612 1613 1614 1615
	   *target_su->array = tswap16(*host_su->array);
           unlock_user_struct(target_su, target_addr, 1);
	   break;
        default:
           gemu_log("semun operation not fully supported: %d\n", (int)cmd);
    }
1616
    return 0;
1617 1618
}

1619 1620
static inline abi_long do_semctl(int first, int second, int third,
                                 abi_long ptr)
1621 1622 1623 1624
{
    union semun arg;
    struct semid_ds dsarg;
    int cmd = third&0xff;
1625
    abi_long ret = 0;
1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664

    switch( cmd ) {
	case GETVAL:
            target_to_host_semun(cmd,&arg,ptr,&dsarg);
            ret = get_errno(semctl(first, second, cmd, arg));
            host_to_target_semun(cmd,ptr,&arg,&dsarg);
            break;
	case SETVAL:
            target_to_host_semun(cmd,&arg,ptr,&dsarg);
            ret = get_errno(semctl(first, second, cmd, arg));
            host_to_target_semun(cmd,ptr,&arg,&dsarg);
            break;
	case GETALL:
            target_to_host_semun(cmd,&arg,ptr,&dsarg);
            ret = get_errno(semctl(first, second, cmd, arg));
            host_to_target_semun(cmd,ptr,&arg,&dsarg);
            break;
	case SETALL:
            target_to_host_semun(cmd,&arg,ptr,&dsarg);
            ret = get_errno(semctl(first, second, cmd, arg));
            host_to_target_semun(cmd,ptr,&arg,&dsarg);
            break;
	case IPC_STAT:
            target_to_host_semun(cmd,&arg,ptr,&dsarg);
            ret = get_errno(semctl(first, second, cmd, arg));
            host_to_target_semun(cmd,ptr,&arg,&dsarg);
            break;
	case IPC_SET:
            target_to_host_semun(cmd,&arg,ptr,&dsarg);
            ret = get_errno(semctl(first, second, cmd, arg));
            host_to_target_semun(cmd,ptr,&arg,&dsarg);
            break;
    default:
            ret = get_errno(semctl(first, second, cmd, arg));
    }

    return ret;
}

T
ths 已提交
1665 1666 1667
struct target_msqid_ds
{
  struct target_ipc_perm msg_perm;
1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680
  abi_ulong msg_stime;
  abi_ulong __unused1;
  abi_ulong msg_rtime;
  abi_ulong __unused2;
  abi_ulong msg_ctime;
  abi_ulong __unused3;
  abi_ulong __msg_cbytes;
  abi_ulong msg_qnum;
  abi_ulong msg_qbytes;
  abi_ulong msg_lspid;
  abi_ulong msg_lrpid;
  abi_ulong __unused4;
  abi_ulong __unused5;
T
ths 已提交
1681 1682
};

1683 1684
static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
                                               abi_ulong target_addr)
T
ths 已提交
1685 1686 1687
{
    struct target_msqid_ds *target_md;

1688 1689
    if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
        return -TARGET_EFAULT;
T
ths 已提交
1690 1691 1692 1693 1694 1695 1696 1697 1698 1699
    target_to_host_ipc_perm(&(host_md->msg_perm),target_addr);
    host_md->msg_stime = tswapl(target_md->msg_stime);
    host_md->msg_rtime = tswapl(target_md->msg_rtime);
    host_md->msg_ctime = tswapl(target_md->msg_ctime);
    host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
    host_md->msg_qnum = tswapl(target_md->msg_qnum);
    host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
    host_md->msg_lspid = tswapl(target_md->msg_lspid);
    host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
    unlock_user_struct(target_md, target_addr, 0);
1700
    return 0;
T
ths 已提交
1701 1702
}

1703 1704
static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
                                               struct msqid_ds *host_md)
T
ths 已提交
1705 1706 1707
{
    struct target_msqid_ds *target_md;

1708 1709
    if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
        return -TARGET_EFAULT;
T
ths 已提交
1710 1711 1712 1713 1714 1715 1716 1717 1718 1719
    host_to_target_ipc_perm(target_addr,&(host_md->msg_perm));
    target_md->msg_stime = tswapl(host_md->msg_stime);
    target_md->msg_rtime = tswapl(host_md->msg_rtime);
    target_md->msg_ctime = tswapl(host_md->msg_ctime);
    target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
    target_md->msg_qnum = tswapl(host_md->msg_qnum);
    target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
    target_md->msg_lspid = tswapl(host_md->msg_lspid);
    target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
    unlock_user_struct(target_md, target_addr, 1);
1720
    return 0;
T
ths 已提交
1721 1722
}

1723
static inline abi_long do_msgctl(int first, int second, abi_long ptr)
T
ths 已提交
1724 1725 1726
{
    struct msqid_ds dsarg;
    int cmd = second&0xff;
1727
    abi_long ret = 0;
T
ths 已提交
1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740
    switch( cmd ) {
    case IPC_STAT:
    case IPC_SET:
        target_to_host_msqid_ds(&dsarg,ptr);
        ret = get_errno(msgctl(first, cmd, &dsarg));
        host_to_target_msqid_ds(ptr,&dsarg);
    default:
        ret = get_errno(msgctl(first, cmd, &dsarg));
    }
    return ret;
}

struct target_msgbuf {
1741
	abi_ulong mtype;
T
ths 已提交
1742 1743 1744
	char	mtext[1];
};

1745 1746
static inline abi_long do_msgsnd(int msqid, abi_long msgp,
                                 unsigned int msgsz, int msgflg)
T
ths 已提交
1747 1748 1749
{
    struct target_msgbuf *target_mb;
    struct msgbuf *host_mb;
1750
    abi_long ret = 0;
T
ths 已提交
1751

1752 1753
    if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
        return -TARGET_EFAULT;
T
ths 已提交
1754 1755 1756 1757 1758 1759 1760 1761 1762 1763
    host_mb = malloc(msgsz+sizeof(long));
    host_mb->mtype = tswapl(target_mb->mtype);
    memcpy(host_mb->mtext,target_mb->mtext,msgsz);
    ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
    free(host_mb);
    unlock_user_struct(target_mb, msgp, 0);

    return ret;
}

1764 1765 1766
static inline abi_long do_msgrcv(int msqid, abi_long msgp,
                                 unsigned int msgsz, int msgtype,
                                 int msgflg)
T
ths 已提交
1767 1768
{
    struct target_msgbuf *target_mb;
1769
    char *target_mtext;
T
ths 已提交
1770
    struct msgbuf *host_mb;
1771
    abi_long ret = 0;
T
ths 已提交
1772

1773 1774
    if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
        return -TARGET_EFAULT;
T
ths 已提交
1775 1776
    host_mb = malloc(msgsz+sizeof(long));
    ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg));
1777 1778 1779 1780 1781 1782 1783
    if (ret > 0) {
        abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
        target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
        if (!target_mtext) {
            ret = -TARGET_EFAULT;
            goto end;
        }
T
ths 已提交
1784
    	memcpy(target_mb->mtext, host_mb->mtext, ret);
1785 1786
        unlock_user(target_mtext, target_mtext_addr, ret);
    }
T
ths 已提交
1787 1788 1789
    target_mb->mtype = tswapl(host_mb->mtype);
    free(host_mb);

1790 1791 1792
end:
    if (target_mb)
        unlock_user_struct(target_mb, msgp, 1);
T
ths 已提交
1793 1794 1795
    return ret;
}

1796
/* ??? This only works with linear mappings.  */
1797
/* do_ipc() must return target values and target errnos. */
1798 1799 1800
static abi_long do_ipc(unsigned int call, int first,
                       int second, int third,
                       abi_long ptr, abi_long fifth)
1801 1802
{
    int version;
1803
    abi_long ret = 0;
1804 1805 1806 1807 1808 1809 1810
    struct shmid_ds shm_info;
    int i;

    version = call >> 16;
    call &= 0xffff;

    switch (call) {
1811
    case IPCOP_semop:
1812
        ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second));
1813 1814 1815 1816 1817 1818 1819
        break;

    case IPCOP_semget:
        ret = get_errno(semget(first, second, third));
        break;

    case IPCOP_semctl:
1820
        ret = do_semctl(first, second, third, ptr);
1821 1822 1823
        break;

    case IPCOP_semtimedop:
1824
        gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
1825
        ret = -TARGET_ENOSYS;
1826
        break;
1827 1828 1829 1830 1831 1832

	case IPCOP_msgget:
		ret = get_errno(msgget(first, second));
		break;

	case IPCOP_msgsnd:
T
ths 已提交
1833
		ret = do_msgsnd(first, ptr, second, third);
1834 1835 1836
		break;

	case IPCOP_msgctl:
T
ths 已提交
1837
        	ret = do_msgctl(first, second, ptr);
1838 1839 1840
		break;

	case IPCOP_msgrcv:
T
ths 已提交
1841
                {
1842
                      /* XXX: this code is not correct */
T
ths 已提交
1843 1844 1845 1846 1847
                      struct ipc_kludge
                      {
                              void *__unbounded msgp;
                              long int msgtyp;
                      };
1848

1849
                      struct ipc_kludge *foo = (struct ipc_kludge *)g2h(ptr);
T
ths 已提交
1850
                      struct msgbuf *msgp = (struct msgbuf *) foo->msgp;
1851

T
ths 已提交
1852
                      ret = do_msgrcv(first, (long)msgp, second, 0, third);
1853

T
ths 已提交
1854
                }
1855 1856
		break;

1857
    case IPCOP_shmat:
1858 1859 1860 1861 1862 1863 1864
        {
            abi_ulong raddr;
            void *host_addr;
            /* SHM_* flags are the same on all linux platforms */
            host_addr = shmat(first, (void *)g2h(ptr), second);
            if (host_addr == (void *)-1) {
                ret = get_errno((long)host_addr);
1865
                break;
1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889
            }
            raddr = h2g((unsigned long)host_addr);
            /* find out the length of the shared memory segment */
            
            ret = get_errno(shmctl(first, IPC_STAT, &shm_info));
            if (is_error(ret)) {
                /* can't get length, bail out */
                shmdt(host_addr);
                break;
            }
            page_set_flags(raddr, raddr + shm_info.shm_segsz,
                           PAGE_VALID | PAGE_READ |
                           ((second & SHM_RDONLY)? 0: PAGE_WRITE));
            for (i = 0; i < N_SHM_REGIONS; ++i) {
                if (shm_regions[i].start == 0) {
                    shm_regions[i].start = raddr;
                    shm_regions[i].size = shm_info.shm_segsz;
                    break;
                }
            }
            if (put_user(raddr, third, abi_ulong))
                return -TARGET_EFAULT;
            ret = 0;
        }
1890 1891 1892 1893 1894 1895 1896 1897 1898
	break;
    case IPCOP_shmdt:
	for (i = 0; i < N_SHM_REGIONS; ++i) {
	    if (shm_regions[i].start == ptr) {
		shm_regions[i].start = 0;
		page_set_flags(ptr, shm_regions[i].size, 0);
		break;
	    }
	}
1899
	ret = get_errno(shmdt((void *)g2h(ptr)));
1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920
	break;

    case IPCOP_shmget:
	/* IPC_* flag values are the same on all linux platforms */
	ret = get_errno(shmget(first, second, third));
	break;

	/* IPC_* and SHM_* command values are the same on all linux platforms */
    case IPCOP_shmctl:
        switch(second) {
        case IPC_RMID:
        case SHM_LOCK:
        case SHM_UNLOCK:
            ret = get_errno(shmctl(first, second, NULL));
            break;
        default:
            goto unimplemented;
        }
        break;
    default:
    unimplemented:
1921
	gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
1922
	ret = -TARGET_ENOSYS;
1923 1924 1925 1926
	break;
    }
    return ret;
}
1927
#endif
1928

1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946
/* kernel structure types definitions */
#define IFNAMSIZ        16

#define STRUCT(name, list...) STRUCT_ ## name,
#define STRUCT_SPECIAL(name) STRUCT_ ## name,
enum {
#include "syscall_types.h"
};
#undef STRUCT
#undef STRUCT_SPECIAL

#define STRUCT(name, list...) const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
#define STRUCT_SPECIAL(name)
#include "syscall_types.h"
#undef STRUCT
#undef STRUCT_SPECIAL

typedef struct IOCTLEntry {
1947 1948
    unsigned int target_cmd;
    unsigned int host_cmd;
1949 1950
    const char *name;
    int access;
B
bellard 已提交
1951
    const argtype arg_type[5];
1952 1953 1954 1955 1956 1957 1958 1959
} IOCTLEntry;

#define IOC_R 0x0001
#define IOC_W 0x0002
#define IOC_RW (IOC_R | IOC_W)

#define MAX_STRUCT_SIZE 4096

1960
IOCTLEntry ioctl_entries[] = {
1961 1962 1963 1964 1965 1966
#define IOCTL(cmd, access, types...) \
    { TARGET_ ## cmd, cmd, #cmd, access, { types } },
#include "ioctls.h"
    { 0, 0, },
};

1967
/* ??? Implement proper locking for ioctls.  */
1968
/* do_ioctl() Must return target values and target errnos. */
1969
static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
1970 1971 1972
{
    const IOCTLEntry *ie;
    const argtype *arg_type;
1973
    abi_long ret;
1974
    uint8_t buf_temp[MAX_STRUCT_SIZE];
1975 1976
    int target_size;
    void *argptr;
1977 1978 1979 1980

    ie = ioctl_entries;
    for(;;) {
        if (ie->target_cmd == 0) {
1981
            gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
1982
            return -TARGET_ENOSYS;
1983 1984 1985 1986 1987 1988
        }
        if (ie->target_cmd == cmd)
            break;
        ie++;
    }
    arg_type = ie->arg_type;
B
bellard 已提交
1989
#if defined(DEBUG)
1990
    gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
B
bellard 已提交
1991
#endif
1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003
    switch(arg_type[0]) {
    case TYPE_NULL:
        /* no argument */
        ret = get_errno(ioctl(fd, ie->host_cmd));
        break;
    case TYPE_PTRVOID:
    case TYPE_INT:
        /* int argment */
        ret = get_errno(ioctl(fd, ie->host_cmd, arg));
        break;
    case TYPE_PTR:
        arg_type++;
2004
        target_size = thunk_type_size(arg_type, 0);
2005 2006 2007 2008
        switch(ie->access) {
        case IOC_R:
            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
            if (!is_error(ret)) {
2009 2010 2011
                argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
                if (!argptr)
                    return -TARGET_EFAULT;
2012 2013
                thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
                unlock_user(argptr, arg, target_size);
2014 2015 2016
            }
            break;
        case IOC_W:
2017 2018 2019
            argptr = lock_user(VERIFY_READ, arg, target_size, 1);
            if (!argptr)
                return -TARGET_EFAULT;
2020 2021
            thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
            unlock_user(argptr, arg, 0);
2022 2023 2024 2025
            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
            break;
        default:
        case IOC_RW:
2026 2027 2028
            argptr = lock_user(VERIFY_READ, arg, target_size, 1);
            if (!argptr)
                return -TARGET_EFAULT;
2029 2030
            thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
            unlock_user(argptr, arg, 0);
2031 2032
            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
            if (!is_error(ret)) {
2033 2034 2035
                argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
                if (!argptr)
                    return -TARGET_EFAULT;
2036 2037
                thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
                unlock_user(argptr, arg, target_size);
2038 2039 2040 2041 2042
            }
            break;
        }
        break;
    default:
2043 2044
        gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
                 (long)cmd, arg_type[0]);
2045
        ret = -TARGET_ENOSYS;
2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154
        break;
    }
    return ret;
}

bitmask_transtbl iflag_tbl[] = {
        { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
        { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
        { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
        { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
        { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
        { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
        { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
        { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
        { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
        { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
        { TARGET_IXON, TARGET_IXON, IXON, IXON },
        { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
        { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
        { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
        { 0, 0, 0, 0 }
};

bitmask_transtbl oflag_tbl[] = {
	{ TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
	{ TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
	{ TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
	{ TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
	{ TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
	{ TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
	{ TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
	{ TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
	{ TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
	{ TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
	{ TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
	{ TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
	{ TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
	{ TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
	{ TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
	{ TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
	{ TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
	{ TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
	{ TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
	{ TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
	{ TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
	{ TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
	{ TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
	{ TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
	{ 0, 0, 0, 0 }
};

bitmask_transtbl cflag_tbl[] = {
	{ TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
	{ TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
	{ TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
	{ TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
	{ TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
	{ TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
	{ TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
	{ TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
	{ TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
	{ TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
	{ TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
	{ TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
	{ TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
	{ TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
	{ TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
	{ TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
	{ TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
	{ TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
	{ TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
	{ TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
	{ TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
	{ TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
	{ TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
	{ TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
	{ TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
	{ TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
	{ TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
	{ TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
	{ TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
	{ TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
	{ TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
	{ 0, 0, 0, 0 }
};

bitmask_transtbl lflag_tbl[] = {
	{ TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
	{ TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
	{ TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
	{ TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
	{ TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
	{ TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
	{ TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
	{ TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
	{ TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
	{ TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
	{ TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
	{ TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
	{ TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
	{ TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
	{ TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
	{ 0, 0, 0, 0 }
};

static void target_to_host_termios (void *dst, const void *src)
{
    struct host_termios *host = dst;
    const struct target_termios *target = src;
2155

2156
    host->c_iflag =
2157
        target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
2158
    host->c_oflag =
2159
        target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
2160
    host->c_cflag =
2161
        target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
2162
    host->c_lflag =
2163 2164
        target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
    host->c_line = target->c_line;
2165

2166 2167
    host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
    host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
2168
    host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
2169
    host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
2170
    host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
2171
    host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
2172
    host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
2173
    host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
2174
    host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
2175 2176
    host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
    host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
2177 2178 2179 2180 2181
    host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
    host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
    host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
    host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
    host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
2182
    host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
2183
}
2184

2185 2186 2187 2188 2189
static void host_to_target_termios (void *dst, const void *src)
{
    struct target_termios *target = dst;
    const struct host_termios *host = src;

2190
    target->c_iflag =
2191
        tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
2192
    target->c_oflag =
2193
        tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
2194
    target->c_cflag =
2195
        tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
2196
    target->c_lflag =
2197 2198
        tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
    target->c_line = host->c_line;
2199

2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224
    target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
    target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
    target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
    target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
    target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
    target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
    target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
    target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
    target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
    target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
    target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
    target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
    target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
    target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
    target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
    target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
    target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
}

StructEntry struct_termios_def = {
    .convert = { host_to_target_termios, target_to_host_termios },
    .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
    .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
};

B
bellard 已提交
2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236
static bitmask_transtbl mmap_flags_tbl[] = {
	{ TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
	{ TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
	{ TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
	{ TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
	{ TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
	{ TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
	{ TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
	{ TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
	{ 0, 0, 0, 0 }
};

B
bellard 已提交
2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250
static bitmask_transtbl fcntl_flags_tbl[] = {
	{ TARGET_O_ACCMODE,   TARGET_O_WRONLY,    O_ACCMODE,   O_WRONLY,    },
	{ TARGET_O_ACCMODE,   TARGET_O_RDWR,      O_ACCMODE,   O_RDWR,      },
	{ TARGET_O_CREAT,     TARGET_O_CREAT,     O_CREAT,     O_CREAT,     },
	{ TARGET_O_EXCL,      TARGET_O_EXCL,      O_EXCL,      O_EXCL,      },
	{ TARGET_O_NOCTTY,    TARGET_O_NOCTTY,    O_NOCTTY,    O_NOCTTY,    },
	{ TARGET_O_TRUNC,     TARGET_O_TRUNC,     O_TRUNC,     O_TRUNC,     },
	{ TARGET_O_APPEND,    TARGET_O_APPEND,    O_APPEND,    O_APPEND,    },
	{ TARGET_O_NONBLOCK,  TARGET_O_NONBLOCK,  O_NONBLOCK,  O_NONBLOCK,  },
	{ TARGET_O_SYNC,      TARGET_O_SYNC,      O_SYNC,      O_SYNC,      },
	{ TARGET_FASYNC,      TARGET_FASYNC,      FASYNC,      FASYNC,      },
	{ TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
	{ TARGET_O_NOFOLLOW,  TARGET_O_NOFOLLOW,  O_NOFOLLOW,  O_NOFOLLOW,  },
	{ TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
B
bellard 已提交
2251
#if defined(O_DIRECT)
B
bellard 已提交
2252
	{ TARGET_O_DIRECT,    TARGET_O_DIRECT,    O_DIRECT,    O_DIRECT,    },
B
bellard 已提交
2253
#endif
B
bellard 已提交
2254 2255 2256
	{ 0, 0, 0, 0 }
};

2257
#if defined(TARGET_I386)
B
bellard 已提交
2258 2259 2260 2261

/* NOTE: there is really one LDT for all the threads */
uint8_t *ldt_table;

2262
static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
B
bellard 已提交
2263 2264
{
    int size;
2265
    void *p;
B
bellard 已提交
2266 2267 2268 2269 2270 2271

    if (!ldt_table)
        return 0;
    size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
    if (size > bytecount)
        size = bytecount;
2272 2273
    p = lock_user(VERIFY_WRITE, ptr, size, 0);
    if (!p)
2274
        return -TARGET_EFAULT;
2275
    /* ??? Should this by byteswapped?  */
2276 2277
    memcpy(p, ldt_table, size);
    unlock_user(p, ptr, size);
B
bellard 已提交
2278 2279 2280 2281
    return size;
}

/* XXX: add locking support */
2282 2283
static abi_long write_ldt(CPUX86State *env,
                          abi_ulong ptr, unsigned long bytecount, int oldmode)
B
bellard 已提交
2284 2285
{
    struct target_modify_ldt_ldt_s ldt_info;
2286
    struct target_modify_ldt_ldt_s *target_ldt_info;
B
bellard 已提交
2287 2288 2289 2290 2291
    int seg_32bit, contents, read_exec_only, limit_in_pages;
    int seg_not_present, useable;
    uint32_t *lp, entry_1, entry_2;

    if (bytecount != sizeof(ldt_info))
2292
        return -TARGET_EINVAL;
2293
    if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
2294
        return -TARGET_EFAULT;
2295 2296 2297 2298 2299
    ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
    ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
    ldt_info.limit = tswap32(target_ldt_info->limit);
    ldt_info.flags = tswap32(target_ldt_info->flags);
    unlock_user_struct(target_ldt_info, ptr, 0);
2300

B
bellard 已提交
2301
    if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
2302
        return -TARGET_EINVAL;
B
bellard 已提交
2303 2304 2305 2306 2307 2308 2309 2310 2311
    seg_32bit = ldt_info.flags & 1;
    contents = (ldt_info.flags >> 1) & 3;
    read_exec_only = (ldt_info.flags >> 3) & 1;
    limit_in_pages = (ldt_info.flags >> 4) & 1;
    seg_not_present = (ldt_info.flags >> 5) & 1;
    useable = (ldt_info.flags >> 6) & 1;

    if (contents == 3) {
        if (oldmode)
2312
            return -TARGET_EINVAL;
B
bellard 已提交
2313
        if (seg_not_present == 0)
2314
            return -TARGET_EINVAL;
B
bellard 已提交
2315 2316 2317 2318 2319
    }
    /* allocate the LDT */
    if (!ldt_table) {
        ldt_table = malloc(TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
        if (!ldt_table)
2320
            return -TARGET_ENOMEM;
B
bellard 已提交
2321
        memset(ldt_table, 0, TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
B
bellard 已提交
2322
        env->ldt.base = h2g((unsigned long)ldt_table);
B
bellard 已提交
2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340
        env->ldt.limit = 0xffff;
    }

    /* NOTE: same code as Linux kernel */
    /* Allow LDTs to be cleared by the user. */
    if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
        if (oldmode ||
            (contents == 0		&&
             read_exec_only == 1	&&
             seg_32bit == 0		&&
             limit_in_pages == 0	&&
             seg_not_present == 1	&&
             useable == 0 )) {
            entry_1 = 0;
            entry_2 = 0;
            goto install;
        }
    }
2341

B
bellard 已提交
2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354
    entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
        (ldt_info.limit & 0x0ffff);
    entry_2 = (ldt_info.base_addr & 0xff000000) |
        ((ldt_info.base_addr & 0x00ff0000) >> 16) |
        (ldt_info.limit & 0xf0000) |
        ((read_exec_only ^ 1) << 9) |
        (contents << 10) |
        ((seg_not_present ^ 1) << 15) |
        (seg_32bit << 22) |
        (limit_in_pages << 23) |
        0x7000;
    if (!oldmode)
        entry_2 |= (useable << 20);
B
bellard 已提交
2355

B
bellard 已提交
2356 2357 2358 2359 2360 2361 2362 2363 2364
    /* Install the new entry ...  */
install:
    lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
    lp[0] = tswap32(entry_1);
    lp[1] = tswap32(entry_2);
    return 0;
}

/* specific and weird i386 syscalls */
2365 2366
abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr, 
                       unsigned long bytecount)
B
bellard 已提交
2367
{
2368
    abi_long ret;
2369

B
bellard 已提交
2370 2371 2372 2373 2374 2375 2376 2377 2378 2379
    switch (func) {
    case 0:
        ret = read_ldt(ptr, bytecount);
        break;
    case 1:
        ret = write_ldt(env, ptr, bytecount, 1);
        break;
    case 0x11:
        ret = write_ldt(env, ptr, bytecount, 0);
        break;
2380 2381 2382
    default:
        ret = -TARGET_ENOSYS;
        break;
B
bellard 已提交
2383 2384 2385
    }
    return ret;
}
B
bellard 已提交
2386

2387 2388
#endif /* defined(TARGET_I386) */

B
bellard 已提交
2389 2390 2391 2392 2393 2394
/* this stack is the equivalent of the kernel stack associated with a
   thread/process */
#define NEW_STACK_SIZE 8192

static int clone_func(void *arg)
{
2395
    CPUState *env = arg;
B
bellard 已提交
2396 2397 2398 2399 2400
    cpu_loop(env);
    /* never exits */
    return 0;
}

2401 2402
/* do_fork() Must return host values and target errnos (unlike most
   do_*() functions). */
2403
int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp)
B
bellard 已提交
2404 2405
{
    int ret;
B
bellard 已提交
2406
    TaskState *ts;
B
bellard 已提交
2407
    uint8_t *new_stack;
2408
    CPUState *new_env;
2409

B
bellard 已提交
2410
    if (flags & CLONE_VM) {
B
bellard 已提交
2411 2412 2413 2414 2415 2416 2417
        ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE);
        memset(ts, 0, sizeof(TaskState));
        new_stack = ts->stack;
        ts->used = 1;
        /* add in task state list */
        ts->next = first_task_state;
        first_task_state = ts;
B
bellard 已提交
2418
        /* we create a new CPU instance. */
2419
        new_env = cpu_copy(env);
2420 2421 2422
#if defined(TARGET_I386)
        if (!newsp)
            newsp = env->regs[R_ESP];
B
bellard 已提交
2423 2424
        new_env->regs[R_ESP] = newsp;
        new_env->regs[R_EAX] = 0;
2425 2426 2427 2428 2429
#elif defined(TARGET_ARM)
        if (!newsp)
            newsp = env->regs[13];
        new_env->regs[13] = newsp;
        new_env->regs[0] = 0;
2430
#elif defined(TARGET_SPARC)
B
bellard 已提交
2431 2432 2433 2434 2435
        if (!newsp)
            newsp = env->regwptr[22];
        new_env->regwptr[22] = newsp;
        new_env->regwptr[0] = 0;
	/* XXXXX */
2436
        printf ("HELPME: %s:%d\n", __FILE__, __LINE__);
P
pbrook 已提交
2437 2438 2439 2440 2441 2442
#elif defined(TARGET_M68K)
        if (!newsp)
            newsp = env->aregs[7];
        new_env->aregs[7] = newsp;
        new_env->dregs[0] = 0;
        /* ??? is this sufficient?  */
B
bellard 已提交
2443
#elif defined(TARGET_MIPS)
T
ths 已提交
2444
        if (!newsp)
2445 2446
            newsp = env->gpr[29][env->current_tc];
        new_env->gpr[29][env->current_tc] = newsp;
2447 2448 2449 2450
#elif defined(TARGET_PPC)
        if (!newsp)
            newsp = env->gpr[1];
        new_env->gpr[1] = newsp;
2451
        {
2452 2453 2454 2455
            int i;
            for (i = 7; i < 32; i++)
                new_env->gpr[i] = 0;
        }
B
bellard 已提交
2456 2457 2458 2459 2460
#elif defined(TARGET_SH4)
	if (!newsp)
	  newsp = env->gregs[15];
	new_env->gregs[15] = newsp;
	/* XXXXX */
2461 2462 2463 2464 2465 2466 2467 2468 2469 2470
#elif defined(TARGET_ALPHA)
       if (!newsp)
         newsp = env->ir[30];
       new_env->ir[30] = newsp;
        /* ? */
        {
            int i;
            for (i = 7; i < 30; i++)
                new_env->ir[i] = 0;
        }
2471 2472 2473 2474
#elif defined(TARGET_CRIS)
	if (!newsp)
	  newsp = env->regs[14];
	new_env->regs[14] = newsp;
2475 2476 2477
#else
#error unsupported target CPU
#endif
B
bellard 已提交
2478
        new_env->opaque = ts;
2479
#ifdef __ia64__
B
bellard 已提交
2480
        ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
2481 2482 2483
#else
	ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
#endif
B
bellard 已提交
2484 2485 2486 2487 2488 2489 2490 2491 2492
    } else {
        /* if no CLONE_VM, we consider it is a fork */
        if ((flags & ~CSIGNAL) != 0)
            return -EINVAL;
        ret = fork();
    }
    return ret;
}

2493
static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
B
bellard 已提交
2494 2495
{
    struct flock fl;
2496
    struct target_flock *target_fl;
2497 2498
    struct flock64 fl64;
    struct target_flock64 *target_fl64;
2499
    abi_long ret;
2500

B
bellard 已提交
2501 2502
    switch(cmd) {
    case TARGET_F_GETLK:
2503 2504
        if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
            return -TARGET_EFAULT;
T
ths 已提交
2505 2506 2507 2508 2509 2510
        fl.l_type = tswap16(target_fl->l_type);
        fl.l_whence = tswap16(target_fl->l_whence);
        fl.l_start = tswapl(target_fl->l_start);
        fl.l_len = tswapl(target_fl->l_len);
        fl.l_pid = tswapl(target_fl->l_pid);
        unlock_user_struct(target_fl, arg, 0);
B
bellard 已提交
2511
        ret = get_errno(fcntl(fd, cmd, &fl));
B
bellard 已提交
2512
        if (ret == 0) {
2513 2514
            if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
                return -TARGET_EFAULT;
B
bellard 已提交
2515 2516 2517 2518 2519
            target_fl->l_type = tswap16(fl.l_type);
            target_fl->l_whence = tswap16(fl.l_whence);
            target_fl->l_start = tswapl(fl.l_start);
            target_fl->l_len = tswapl(fl.l_len);
            target_fl->l_pid = tswapl(fl.l_pid);
2520
            unlock_user_struct(target_fl, arg, 1);
B
bellard 已提交
2521 2522
        }
        break;
2523

B
bellard 已提交
2524 2525
    case TARGET_F_SETLK:
    case TARGET_F_SETLKW:
2526 2527
        if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
            return -TARGET_EFAULT;
B
bellard 已提交
2528 2529 2530 2531 2532
        fl.l_type = tswap16(target_fl->l_type);
        fl.l_whence = tswap16(target_fl->l_whence);
        fl.l_start = tswapl(target_fl->l_start);
        fl.l_len = tswapl(target_fl->l_len);
        fl.l_pid = tswapl(target_fl->l_pid);
2533
        unlock_user_struct(target_fl, arg, 0);
B
bellard 已提交
2534
        ret = get_errno(fcntl(fd, cmd, &fl));
B
bellard 已提交
2535
        break;
2536

B
bellard 已提交
2537
    case TARGET_F_GETLK64:
2538 2539
        if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
            return -TARGET_EFAULT;
T
ths 已提交
2540 2541 2542 2543 2544 2545
        fl64.l_type = tswap16(target_fl64->l_type) >> 1;
        fl64.l_whence = tswap16(target_fl64->l_whence);
        fl64.l_start = tswapl(target_fl64->l_start);
        fl64.l_len = tswapl(target_fl64->l_len);
        fl64.l_pid = tswap16(target_fl64->l_pid);
        unlock_user_struct(target_fl64, arg, 0);
B
bellard 已提交
2546
        ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
2547
        if (ret == 0) {
2548 2549
            if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
                return -TARGET_EFAULT;
2550 2551 2552 2553 2554 2555 2556
            target_fl64->l_type = tswap16(fl64.l_type) >> 1;
            target_fl64->l_whence = tswap16(fl64.l_whence);
            target_fl64->l_start = tswapl(fl64.l_start);
            target_fl64->l_len = tswapl(fl64.l_len);
            target_fl64->l_pid = tswapl(fl64.l_pid);
            unlock_user_struct(target_fl64, arg, 1);
        }
B
bellard 已提交
2557
        break;
B
bellard 已提交
2558 2559
    case TARGET_F_SETLK64:
    case TARGET_F_SETLKW64:
2560 2561
        if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
            return -TARGET_EFAULT;
2562 2563 2564 2565 2566 2567
        fl64.l_type = tswap16(target_fl64->l_type) >> 1;
        fl64.l_whence = tswap16(target_fl64->l_whence);
        fl64.l_start = tswapl(target_fl64->l_start);
        fl64.l_len = tswapl(target_fl64->l_len);
        fl64.l_pid = tswap16(target_fl64->l_pid);
        unlock_user_struct(target_fl64, arg, 0);
B
bellard 已提交
2568
        ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
B
bellard 已提交
2569 2570
        break;

B
bellard 已提交
2571
    case F_GETFL:
B
bellard 已提交
2572 2573 2574 2575
        ret = get_errno(fcntl(fd, cmd, arg));
        if (ret >= 0) {
            ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
        }
B
bellard 已提交
2576 2577 2578
        break;

    case F_SETFL:
B
bellard 已提交
2579
        ret = get_errno(fcntl(fd, cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
B
bellard 已提交
2580 2581
        break;

B
bellard 已提交
2582
    default:
B
bellard 已提交
2583
        ret = get_errno(fcntl(fd, cmd, arg));
B
bellard 已提交
2584 2585 2586 2587 2588
        break;
    }
    return ret;
}

2589
#ifdef USE_UID16
B
bellard 已提交
2590

2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623
static inline int high2lowuid(int uid)
{
    if (uid > 65535)
        return 65534;
    else
        return uid;
}

static inline int high2lowgid(int gid)
{
    if (gid > 65535)
        return 65534;
    else
        return gid;
}

static inline int low2highuid(int uid)
{
    if ((int16_t)uid == -1)
        return -1;
    else
        return uid;
}

static inline int low2highgid(int gid)
{
    if ((int16_t)gid == -1)
        return -1;
    else
        return gid;
}

#endif /* USE_UID16 */
B
bellard 已提交
2624

2625 2626
void syscall_init(void)
{
2627 2628 2629
    IOCTLEntry *ie;
    const argtype *arg_type;
    int size;
2630
    int i;
2631

2632 2633
#define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
2634 2635 2636
#include "syscall_types.h"
#undef STRUCT
#undef STRUCT_SPECIAL
2637 2638 2639 2640 2641 2642 2643 2644 2645

    /* we patch the ioctl size if necessary. We rely on the fact that
       no ioctl has all the bits at '1' in the size field */
    ie = ioctl_entries;
    while (ie->target_cmd != 0) {
        if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
            TARGET_IOC_SIZEMASK) {
            arg_type = ie->arg_type;
            if (arg_type[0] != TYPE_PTR) {
2646
                fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
2647 2648 2649 2650 2651
                        ie->target_cmd);
                exit(1);
            }
            arg_type++;
            size = thunk_type_size(arg_type, 0);
2652
            ie->target_cmd = (ie->target_cmd &
2653 2654 2655
                              ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
                (size << TARGET_IOC_SIZESHIFT);
        }
2656 2657 2658 2659 2660 2661

        /* Build target_to_host_errno_table[] table from
         * host_to_target_errno_table[]. */
        for (i=0; i < ERRNO_TABLE_SIZE; i++)
                target_to_host_errno_table[host_to_target_errno_table[i]] = i;

2662 2663 2664
        /* automatic consistency check if same arch */
#if defined(__i386__) && defined(TARGET_I386)
        if (ie->target_cmd != ie->host_cmd) {
2665
            fprintf(stderr, "ERROR: ioctl: target=0x%x host=0x%x\n",
2666 2667 2668 2669 2670
                    ie->target_cmd, ie->host_cmd);
        }
#endif
        ie++;
    }
2671
}
B
bellard 已提交
2672

2673
#if TARGET_ABI_BITS == 32
P
pbrook 已提交
2674 2675 2676 2677 2678 2679 2680 2681
static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
{
#ifdef TARGET_WORDS_BIG_ENDIAN
    return ((uint64_t)word0 << 32) | word1;
#else
    return ((uint64_t)word1 << 32) | word0;
#endif
}
2682
#else /* TARGET_ABI_BITS == 32 */
2683 2684 2685 2686
static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
{
    return word0;
}
2687
#endif /* TARGET_ABI_BITS != 32 */
P
pbrook 已提交
2688 2689

#ifdef TARGET_NR_truncate64
2690 2691 2692 2693
static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
                                         abi_long arg2,
                                         abi_long arg3,
                                         abi_long arg4)
P
pbrook 已提交
2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706
{
#ifdef TARGET_ARM
    if (((CPUARMState *)cpu_env)->eabi)
      {
        arg2 = arg3;
        arg3 = arg4;
      }
#endif
    return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
}
#endif

#ifdef TARGET_NR_ftruncate64
2707 2708 2709 2710
static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
                                          abi_long arg2,
                                          abi_long arg3,
                                          abi_long arg4)
P
pbrook 已提交
2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722
{
#ifdef TARGET_ARM
    if (((CPUARMState *)cpu_env)->eabi)
      {
        arg2 = arg3;
        arg3 = arg4;
      }
#endif
    return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
}
#endif

2723 2724
static inline abi_long target_to_host_timespec(struct timespec *host_ts,
                                               abi_ulong target_addr)
2725 2726 2727
{
    struct target_timespec *target_ts;

2728 2729
    if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
        return -TARGET_EFAULT;
2730 2731 2732 2733 2734
    host_ts->tv_sec = tswapl(target_ts->tv_sec);
    host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
    unlock_user_struct(target_ts, target_addr, 0);
}

2735 2736
static inline abi_long host_to_target_timespec(abi_ulong target_addr,
                                               struct timespec *host_ts)
2737 2738 2739
{
    struct target_timespec *target_ts;

2740 2741
    if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
        return -TARGET_EFAULT;
2742 2743 2744 2745 2746
    target_ts->tv_sec = tswapl(host_ts->tv_sec);
    target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
    unlock_user_struct(target_ts, target_addr, 1);
}

2747 2748 2749
/* do_syscall() should always have a single exit point at the end so
   that actions, such as logging of syscall results, can be performed.
   All errnos that do_syscall() returns must be -TARGET_<errcode>. */
2750 2751 2752
abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                    abi_long arg2, abi_long arg3, abi_long arg4,
                    abi_long arg5, abi_long arg6)
2753
{
2754
    abi_long ret;
2755
    struct stat st;
B
bellard 已提交
2756
    struct statfs stfs;
2757
    void *p;
2758

B
bellard 已提交
2759
#ifdef DEBUG
B
bellard 已提交
2760
    gemu_log("syscall %d", num);
B
bellard 已提交
2761
#endif
2762 2763 2764
    if(do_strace)
        print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);

2765 2766
    switch(num) {
    case TARGET_NR_exit:
B
bellard 已提交
2767 2768 2769
#ifdef HAVE_GPROF
        _mcleanup();
#endif
2770
        gdb_exit(cpu_env, arg1);
B
bellard 已提交
2771
        /* XXX: should free thread stack and CPU env */
2772 2773 2774 2775
        _exit(arg1);
        ret = 0; /* avoid warning */
        break;
    case TARGET_NR_read:
2776 2777
        if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
            goto efault;
2778 2779
        ret = get_errno(read(arg1, p, arg3));
        unlock_user(p, arg2, ret);
2780 2781
        break;
    case TARGET_NR_write:
2782 2783
        if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
            goto efault;
2784 2785
        ret = get_errno(write(arg1, p, arg3));
        unlock_user(p, arg2, 0);
2786 2787
        break;
    case TARGET_NR_open:
2788 2789 2790 2791
        if (!(p = lock_user_string(arg1))) {
            return -TARGET_EFAULT;
            goto fail;
        }
2792
        ret = get_errno(open(path(p),
B
bellard 已提交
2793 2794
                             target_to_host_bitmask(arg2, fcntl_flags_tbl),
                             arg3));
2795
        unlock_user(p, arg1, 0);
2796
        break;
2797 2798
#if defined(TARGET_NR_openat) && defined(__NR_openat)
    case TARGET_NR_openat:
2799 2800 2801 2802 2803 2804 2805
        if (!(p = lock_user_string(arg2)))
            goto efault;
        ret = get_errno(sys_openat(arg1,
                                   path(p),
                                   target_to_host_bitmask(arg3, fcntl_flags_tbl),
                                   arg4));
        unlock_user(p, arg2, 0);
2806 2807
        break;
#endif
2808 2809 2810 2811
    case TARGET_NR_close:
        ret = get_errno(close(arg1));
        break;
    case TARGET_NR_brk:
2812
        ret = do_brk(arg1);
2813 2814
        break;
    case TARGET_NR_fork:
B
bellard 已提交
2815
        ret = get_errno(do_fork(cpu_env, SIGCHLD, 0));
2816
        break;
2817
#ifdef TARGET_NR_waitpid
2818 2819
    case TARGET_NR_waitpid:
        {
2820 2821 2822 2823
            int status;
            ret = get_errno(waitpid(arg1, &status, arg3));
            if (!is_error(ret) && arg2)
                tput32(arg2, status);
2824 2825
        }
        break;
2826
#endif
2827
#ifdef TARGET_NR_creat /* not on alpha */
2828
    case TARGET_NR_creat:
2829 2830
        if (!(p = lock_user_string(arg1)))
            goto efault;
2831 2832
        ret = get_errno(creat(p, arg2));
        unlock_user(p, arg1, 0);
2833
        break;
2834
#endif
2835
    case TARGET_NR_link:
2836 2837 2838 2839
        {
            void * p2;
            p = lock_user_string(arg1);
            p2 = lock_user_string(arg2);
2840 2841 2842 2843
            if (!p || !p2)
                ret = -TARGET_EFAULT;
            else
                ret = get_errno(link(p, p2));
2844 2845 2846
            unlock_user(p2, arg2, 0);
            unlock_user(p, arg1, 0);
        }
2847
        break;
2848 2849 2850 2851
#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
    case TARGET_NR_linkat:
        {
            void * p2 = NULL;
2852 2853
            if (!arg2 || !arg4)
                goto efault;
2854 2855
            p  = lock_user_string(arg2);
            p2 = lock_user_string(arg4);
2856
            if (!p || !p2)
2857
                ret = -TARGET_EFAULT;
2858 2859
            else
                ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
2860 2861
            unlock_user(p, arg2, 0);
            unlock_user(p2, arg4, 0);
2862 2863 2864
        }
        break;
#endif
2865
    case TARGET_NR_unlink:
2866 2867
        if (!(p = lock_user_string(arg1)))
            goto efault;
2868 2869
        ret = get_errno(unlink(p));
        unlock_user(p, arg1, 0);
2870
        break;
2871 2872
#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
    case TARGET_NR_unlinkat:
2873 2874 2875 2876
        if (!(p = lock_user_string(arg2)))
            goto efault;
        ret = get_errno(sys_unlinkat(arg1, p, arg3));
        unlock_user(p, arg2, 0);
2877
#endif
2878
    case TARGET_NR_execve:
B
bellard 已提交
2879 2880
        {
            char **argp, **envp;
B
bellard 已提交
2881
            int argc, envc;
2882 2883 2884 2885
            abi_ulong gp;
            abi_ulong guest_argp;
            abi_ulong guest_envp;
            abi_ulong addr;
B
bellard 已提交
2886 2887
            char **q;

B
bellard 已提交
2888
            argc = 0;
2889 2890
            guest_argp = arg2;
            for (gp = guest_argp; tgetl(gp); gp++)
B
bellard 已提交
2891
                argc++;
B
bellard 已提交
2892
            envc = 0;
2893 2894
            guest_envp = arg3;
            for (gp = guest_envp; tgetl(gp); gp++)
B
bellard 已提交
2895 2896
                envc++;

B
bellard 已提交
2897 2898
            argp = alloca((argc + 1) * sizeof(void *));
            envp = alloca((envc + 1) * sizeof(void *));
B
bellard 已提交
2899

2900
            for (gp = guest_argp, q = argp; ;
2901
                  gp += sizeof(abi_ulong), q++) {
2902 2903 2904
                addr = tgetl(gp);
                if (!addr)
                    break;
2905 2906 2907 2908
                if (!(*q = lock_user_string(addr))) {
                    ret = -TARGET_EFAULT;
                    goto execve_fail;
                }
2909
            }
B
bellard 已提交
2910 2911
            *q = NULL;

2912
            for (gp = guest_envp, q = envp; ;
2913
                  gp += sizeof(abi_ulong), q++) {
2914 2915 2916
                addr = tgetl(gp);
                if (!addr)
                    break;
2917 2918 2919 2920
                if (!(*q = lock_user_string(addr))) {
                    ret = -TARGET_EFAULT;
                    goto execve_fail;
                }
2921
            }
B
bellard 已提交
2922
            *q = NULL;
B
bellard 已提交
2923

2924 2925 2926 2927
            if (!(p = lock_user_string(arg1))) {
                ret = -TARGET_EFAULT;
                goto execve_fail;
            }
2928 2929 2930
            ret = get_errno(execve(p, argp, envp));
            unlock_user(p, arg1, 0);

2931
        execve_fail:
2932
            for (gp = guest_argp, q = argp; *q;
2933
                  gp += sizeof(abi_ulong), q++) {
2934 2935 2936 2937
                addr = tgetl(gp);
                unlock_user(*q, addr, 0);
            }
            for (gp = guest_envp, q = envp; *q;
2938
                  gp += sizeof(abi_ulong), q++) {
2939 2940 2941
                addr = tgetl(gp);
                unlock_user(*q, addr, 0);
            }
B
bellard 已提交
2942
        }
2943 2944
        break;
    case TARGET_NR_chdir:
2945 2946
        if (!(p = lock_user_string(arg1)))
            goto efault;
2947 2948
        ret = get_errno(chdir(p));
        unlock_user(p, arg1, 0);
2949
        break;
B
bellard 已提交
2950
#ifdef TARGET_NR_time
2951 2952
    case TARGET_NR_time:
        {
2953 2954 2955 2956
            time_t host_time;
            ret = get_errno(time(&host_time));
            if (!is_error(ret) && arg1)
                tputl(arg1, host_time);
2957 2958
        }
        break;
B
bellard 已提交
2959
#endif
2960
    case TARGET_NR_mknod:
2961 2962
        if (!(p = lock_user_string(arg1)))
            goto efault;
2963 2964
        ret = get_errno(mknod(p, arg2, arg3));
        unlock_user(p, arg1, 0);
2965
        break;
2966 2967
#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
    case TARGET_NR_mknodat:
2968 2969 2970 2971
        if (!(p = lock_user_string(arg2)))
            goto efault;
        ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
        unlock_user(p, arg2, 0);
2972 2973
        break;
#endif
2974
    case TARGET_NR_chmod:
2975 2976
        if (!(p = lock_user_string(arg1)))
            goto efault;
2977 2978
        ret = get_errno(chmod(p, arg2));
        unlock_user(p, arg1, 0);
2979
        break;
2980
#ifdef TARGET_NR_break
2981 2982
    case TARGET_NR_break:
        goto unimplemented;
2983 2984
#endif
#ifdef TARGET_NR_oldstat
2985 2986
    case TARGET_NR_oldstat:
        goto unimplemented;
2987
#endif
2988 2989 2990
    case TARGET_NR_lseek:
        ret = get_errno(lseek(arg1, arg2, arg3));
        break;
2991 2992 2993
#ifdef TARGET_NR_getxpid
    case TARGET_NR_getxpid:
#else
2994
    case TARGET_NR_getpid:
2995
#endif
2996 2997 2998
        ret = get_errno(getpid());
        break;
    case TARGET_NR_mount:
2999 3000 3001 3002 3003 3004
		{
			/* need to look at the data field */
			void *p2, *p3;
			p = lock_user_string(arg1);
			p2 = lock_user_string(arg2);
			p3 = lock_user_string(arg3);
3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015
                        if (!p || !p2 || !p3)
                            ret = -TARGET_EFAULT;
                        else
                            /* FIXME - arg5 should be locked, but it isn't clear how to
                             * do that since it's not guaranteed to be a NULL-terminated
                             * string.
                             */
                            ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
                        unlock_user(p, arg1, 0);
                        unlock_user(p2, arg2, 0);
                        unlock_user(p3, arg3, 0);
3016 3017
			break;
		}
3018
#ifdef TARGET_NR_umount
3019
    case TARGET_NR_umount:
3020 3021
        if (!(p = lock_user_string(arg1)))
            goto efault;
3022 3023
        ret = get_errno(umount(p));
        unlock_user(p, arg1, 0);
3024
        break;
3025
#endif
3026
#ifdef TARGET_NR_stime /* not on alpha */
3027 3028
    case TARGET_NR_stime:
        {
3029 3030 3031
            time_t host_time;
            host_time = tgetl(arg1);
            ret = get_errno(stime(&host_time));
3032 3033
        }
        break;
3034
#endif
3035 3036
    case TARGET_NR_ptrace:
        goto unimplemented;
3037
#ifdef TARGET_NR_alarm /* not on alpha */
3038 3039 3040
    case TARGET_NR_alarm:
        ret = alarm(arg1);
        break;
3041
#endif
3042
#ifdef TARGET_NR_oldfstat
3043 3044
    case TARGET_NR_oldfstat:
        goto unimplemented;
3045
#endif
3046
#ifdef TARGET_NR_pause /* not on alpha */
3047 3048 3049
    case TARGET_NR_pause:
        ret = get_errno(pause());
        break;
3050
#endif
3051
#ifdef TARGET_NR_utime
3052
    case TARGET_NR_utime:
3053
        {
3054 3055 3056
            struct utimbuf tbuf, *host_tbuf;
            struct target_utimbuf *target_tbuf;
            if (arg2) {
3057 3058
                if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
                    goto efault;
3059 3060 3061 3062
                tbuf.actime = tswapl(target_tbuf->actime);
                tbuf.modtime = tswapl(target_tbuf->modtime);
                unlock_user_struct(target_tbuf, arg2, 0);
                host_tbuf = &tbuf;
B
bellard 已提交
3063
            } else {
3064
                host_tbuf = NULL;
B
bellard 已提交
3065
            }
3066 3067
            if (!(p = lock_user_string(arg1)))
                goto efault;
3068 3069
            ret = get_errno(utime(p, host_tbuf));
            unlock_user(p, arg1, 0);
3070 3071
        }
        break;
3072
#endif
B
bellard 已提交
3073 3074 3075
    case TARGET_NR_utimes:
        {
            struct timeval *tvp, tv[2];
3076 3077 3078 3079
            if (arg2) {
                target_to_host_timeval(&tv[0], arg2);
                target_to_host_timeval(&tv[1],
                    arg2 + sizeof (struct target_timeval));
B
bellard 已提交
3080 3081 3082 3083
                tvp = tv;
            } else {
                tvp = NULL;
            }
3084 3085
            if (!(p = lock_user_string(arg1)))
                goto efault;
3086 3087
            ret = get_errno(utimes(p, tvp));
            unlock_user(p, arg1, 0);
B
bellard 已提交
3088 3089
        }
        break;
3090
#ifdef TARGET_NR_stty
3091 3092
    case TARGET_NR_stty:
        goto unimplemented;
3093 3094
#endif
#ifdef TARGET_NR_gtty
3095 3096
    case TARGET_NR_gtty:
        goto unimplemented;
3097
#endif
3098
    case TARGET_NR_access:
3099 3100
        if (!(p = lock_user_string(arg1)))
            goto efault;
3101 3102
        ret = get_errno(access(p, arg2));
        unlock_user(p, arg1, 0);
3103
        break;
3104 3105
#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
    case TARGET_NR_faccessat:
3106 3107 3108 3109
        if (!(p = lock_user_string(arg2)))
            goto efault;
        ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
        unlock_user(p, arg2, 0);
3110 3111
        break;
#endif
3112
#ifdef TARGET_NR_nice /* not on alpha */
3113 3114 3115
    case TARGET_NR_nice:
        ret = get_errno(nice(arg1));
        break;
3116
#endif
3117
#ifdef TARGET_NR_ftime
3118 3119
    case TARGET_NR_ftime:
        goto unimplemented;
3120
#endif
3121
    case TARGET_NR_sync:
B
bellard 已提交
3122 3123
        sync();
        ret = 0;
3124 3125 3126 3127 3128
        break;
    case TARGET_NR_kill:
        ret = get_errno(kill(arg1, arg2));
        break;
    case TARGET_NR_rename:
3129 3130 3131 3132
        {
            void *p2;
            p = lock_user_string(arg1);
            p2 = lock_user_string(arg2);
3133 3134 3135 3136
            if (!p || !p2)
                ret = -TARGET_EFAULT;
            else
                ret = get_errno(rename(p, p2));
3137 3138 3139
            unlock_user(p2, arg2, 0);
            unlock_user(p, arg1, 0);
        }
3140
        break;
3141 3142 3143
#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
    case TARGET_NR_renameat:
        {
3144
            void *p2;
3145 3146
            p  = lock_user_string(arg2);
            p2 = lock_user_string(arg4);
3147
            if (!p || !p2)
3148
                ret = -TARGET_EFAULT;
3149 3150
            else
                ret = get_errno(sys_renameat(arg1, p, arg3, p2));
3151 3152
            unlock_user(p2, arg4, 0);
            unlock_user(p, arg2, 0);
3153 3154 3155
        }
        break;
#endif
3156
    case TARGET_NR_mkdir:
3157 3158
        if (!(p = lock_user_string(arg1)))
            goto efault;
3159 3160
        ret = get_errno(mkdir(p, arg2));
        unlock_user(p, arg1, 0);
3161
        break;
3162 3163
#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
    case TARGET_NR_mkdirat:
3164 3165 3166 3167
        if (!(p = lock_user_string(arg2)))
            goto efault;
        ret = get_errno(sys_mkdirat(arg1, p, arg3));
        unlock_user(p, arg2, 0);
3168 3169
        break;
#endif
3170
    case TARGET_NR_rmdir:
3171 3172
        if (!(p = lock_user_string(arg1)))
            goto efault;
3173 3174
        ret = get_errno(rmdir(p));
        unlock_user(p, arg1, 0);
3175 3176 3177 3178 3179 3180
        break;
    case TARGET_NR_dup:
        ret = get_errno(dup(arg1));
        break;
    case TARGET_NR_pipe:
        {
3181 3182
            int host_pipe[2];
            ret = get_errno(pipe(host_pipe));
3183
            if (!is_error(ret)) {
3184
#if defined(TARGET_MIPS)
3185 3186
                CPUMIPSState *env = (CPUMIPSState*)cpu_env;
		env->gpr[3][env->current_tc] = host_pipe[1];
3187 3188
		ret = host_pipe[0];
#else
3189 3190
                tput32(arg1, host_pipe[0]);
                tput32(arg1 + 4, host_pipe[1]);
3191
#endif
3192 3193 3194 3195
            }
        }
        break;
    case TARGET_NR_times:
B
bellard 已提交
3196
        {
3197
            struct target_tms *tmsp;
B
bellard 已提交
3198 3199
            struct tms tms;
            ret = get_errno(times(&tms));
3200
            if (arg1) {
3201 3202 3203
                tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
                if (!tmsp)
                    goto efault;
B
bellard 已提交
3204 3205 3206 3207
                tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
                tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
                tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
                tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
B
bellard 已提交
3208
            }
B
bellard 已提交
3209 3210
            if (!is_error(ret))
                ret = host_to_target_clock_t(ret);
B
bellard 已提交
3211 3212
        }
        break;
3213
#ifdef TARGET_NR_prof
3214 3215
    case TARGET_NR_prof:
        goto unimplemented;
3216
#endif
3217
#ifdef TARGET_NR_signal
3218 3219
    case TARGET_NR_signal:
        goto unimplemented;
3220
#endif
3221
    case TARGET_NR_acct:
3222 3223
        if (!(p = lock_user_string(arg1)))
            goto efault;
3224 3225 3226
        ret = get_errno(acct(path(p)));
        unlock_user(p, arg1, 0);
        break;
3227
#ifdef TARGET_NR_umount2 /* not on alpha */
3228
    case TARGET_NR_umount2:
3229 3230
        if (!(p = lock_user_string(arg1)))
            goto efault;
3231 3232
        ret = get_errno(umount2(p, arg2));
        unlock_user(p, arg1, 0);
3233
        break;
3234
#endif
3235
#ifdef TARGET_NR_lock
3236 3237
    case TARGET_NR_lock:
        goto unimplemented;
3238
#endif
3239 3240 3241 3242
    case TARGET_NR_ioctl:
        ret = do_ioctl(arg1, arg2, arg3);
        break;
    case TARGET_NR_fcntl:
B
bellard 已提交
3243
        ret = do_fcntl(arg1, arg2, arg3);
3244
        break;
3245
#ifdef TARGET_NR_mpx
3246 3247
    case TARGET_NR_mpx:
        goto unimplemented;
3248
#endif
3249 3250 3251
    case TARGET_NR_setpgid:
        ret = get_errno(setpgid(arg1, arg2));
        break;
3252
#ifdef TARGET_NR_ulimit
3253 3254
    case TARGET_NR_ulimit:
        goto unimplemented;
3255 3256
#endif
#ifdef TARGET_NR_oldolduname
3257 3258
    case TARGET_NR_oldolduname:
        goto unimplemented;
3259
#endif
3260 3261 3262 3263
    case TARGET_NR_umask:
        ret = get_errno(umask(arg1));
        break;
    case TARGET_NR_chroot:
3264 3265
        if (!(p = lock_user_string(arg1)))
            goto efault;
3266 3267
        ret = get_errno(chroot(p));
        unlock_user(p, arg1, 0);
3268 3269 3270 3271 3272 3273
        break;
    case TARGET_NR_ustat:
        goto unimplemented;
    case TARGET_NR_dup2:
        ret = get_errno(dup2(arg1, arg2));
        break;
3274
#ifdef TARGET_NR_getppid /* not on alpha */
3275 3276 3277
    case TARGET_NR_getppid:
        ret = get_errno(getppid());
        break;
3278
#endif
3279 3280 3281 3282 3283 3284
    case TARGET_NR_getpgrp:
        ret = get_errno(getpgrp());
        break;
    case TARGET_NR_setsid:
        ret = get_errno(setsid());
        break;
3285
#ifdef TARGET_NR_sigaction
3286 3287
    case TARGET_NR_sigaction:
        {
T
ths 已提交
3288
#if !defined(TARGET_MIPS)
3289
            struct target_old_sigaction *old_act;
B
bellard 已提交
3290
            struct target_sigaction act, oact, *pact;
3291
            if (arg2) {
3292 3293
                if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
                    goto efault;
B
bellard 已提交
3294 3295 3296 3297
                act._sa_handler = old_act->_sa_handler;
                target_siginitset(&act.sa_mask, old_act->sa_mask);
                act.sa_flags = old_act->sa_flags;
                act.sa_restorer = old_act->sa_restorer;
3298
                unlock_user_struct(old_act, arg2, 0);
B
bellard 已提交
3299 3300 3301 3302 3303
                pact = &act;
            } else {
                pact = NULL;
            }
            ret = get_errno(do_sigaction(arg1, pact, &oact));
3304
            if (!is_error(ret) && arg3) {
3305 3306
                if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
                    goto efault;
3307 3308 3309 3310 3311
                old_act->_sa_handler = oact._sa_handler;
                old_act->sa_mask = oact.sa_mask.sig[0];
                old_act->sa_flags = oact.sa_flags;
                old_act->sa_restorer = oact.sa_restorer;
                unlock_user_struct(old_act, arg3, 1);
B
bellard 已提交
3312
            }
T
ths 已提交
3313
#else
3314 3315 3316
	    struct target_sigaction act, oact, *pact, *old_act;

	    if (arg2) {
3317 3318
                if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
                    goto efault;
3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330
		act._sa_handler = old_act->_sa_handler;
		target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
		act.sa_flags = old_act->sa_flags;
		unlock_user_struct(old_act, arg2, 0);
		pact = &act;
	    } else {
		pact = NULL;
	    }

	    ret = get_errno(do_sigaction(arg1, pact, &oact));

	    if (!is_error(ret) && arg3) {
3331 3332
                if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
                    goto efault;
3333 3334 3335 3336 3337 3338 3339 3340
		old_act->_sa_handler = oact._sa_handler;
		old_act->sa_flags = oact.sa_flags;
		old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
		old_act->sa_mask.sig[1] = 0;
		old_act->sa_mask.sig[2] = 0;
		old_act->sa_mask.sig[3] = 0;
		unlock_user_struct(old_act, arg3, 1);
	    }
T
ths 已提交
3341
#endif
3342 3343
        }
        break;
3344
#endif
B
bellard 已提交
3345
    case TARGET_NR_rt_sigaction:
3346 3347 3348 3349
        {
            struct target_sigaction *act;
            struct target_sigaction *oact;

3350 3351 3352 3353
            if (arg2) {
                if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
                    goto efault;
            } else
3354
                act = NULL;
3355 3356 3357 3358 3359 3360
            if (arg3) {
                if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
                    ret = -TARGET_EFAULT;
                    goto rt_sigaction_fail;
                }
            } else
3361 3362
                oact = NULL;
            ret = get_errno(do_sigaction(arg1, act, oact));
3363 3364
	rt_sigaction_fail:
            if (act)
3365
                unlock_user_struct(act, arg2, 0);
3366
            if (oact)
3367 3368
                unlock_user_struct(oact, arg3, 1);
        }
B
bellard 已提交
3369
        break;
3370
#ifdef TARGET_NR_sgetmask /* not on alpha */
3371
    case TARGET_NR_sgetmask:
B
bellard 已提交
3372 3373
        {
            sigset_t cur_set;
3374
            abi_ulong target_set;
B
bellard 已提交
3375 3376 3377 3378 3379
            sigprocmask(0, NULL, &cur_set);
            host_to_target_old_sigset(&target_set, &cur_set);
            ret = target_set;
        }
        break;
3380 3381
#endif
#ifdef TARGET_NR_ssetmask /* not on alpha */
3382
    case TARGET_NR_ssetmask:
B
bellard 已提交
3383 3384
        {
            sigset_t set, oset, cur_set;
3385
            abi_ulong target_set = arg1;
B
bellard 已提交
3386 3387 3388 3389 3390 3391 3392 3393
            sigprocmask(0, NULL, &cur_set);
            target_to_host_old_sigset(&set, &target_set);
            sigorset(&set, &set, &cur_set);
            sigprocmask(SIG_SETMASK, &set, &oset);
            host_to_target_old_sigset(&target_set, &oset);
            ret = target_set;
        }
        break;
3394
#endif
3395
#ifdef TARGET_NR_sigprocmask
B
bellard 已提交
3396 3397 3398 3399
    case TARGET_NR_sigprocmask:
        {
            int how = arg1;
            sigset_t set, oldset, *set_ptr;
3400

3401
            if (arg2) {
B
bellard 已提交
3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412
                switch(how) {
                case TARGET_SIG_BLOCK:
                    how = SIG_BLOCK;
                    break;
                case TARGET_SIG_UNBLOCK:
                    how = SIG_UNBLOCK;
                    break;
                case TARGET_SIG_SETMASK:
                    how = SIG_SETMASK;
                    break;
                default:
3413
                    ret = -TARGET_EINVAL;
B
bellard 已提交
3414 3415
                    goto fail;
                }
3416 3417
                if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
                    goto efault;
3418 3419
                target_to_host_old_sigset(&set, p);
                unlock_user(p, arg2, 0);
B
bellard 已提交
3420 3421 3422 3423 3424 3425
                set_ptr = &set;
            } else {
                how = 0;
                set_ptr = NULL;
            }
            ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
3426
            if (!is_error(ret) && arg3) {
3427 3428
                if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
                    goto efault;
3429 3430
                host_to_target_old_sigset(p, &oldset);
                unlock_user(p, arg3, sizeof(target_sigset_t));
B
bellard 已提交
3431 3432 3433
            }
        }
        break;
3434
#endif
B
bellard 已提交
3435 3436 3437 3438
    case TARGET_NR_rt_sigprocmask:
        {
            int how = arg1;
            sigset_t set, oldset, *set_ptr;
3439

3440
            if (arg2) {
B
bellard 已提交
3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451
                switch(how) {
                case TARGET_SIG_BLOCK:
                    how = SIG_BLOCK;
                    break;
                case TARGET_SIG_UNBLOCK:
                    how = SIG_UNBLOCK;
                    break;
                case TARGET_SIG_SETMASK:
                    how = SIG_SETMASK;
                    break;
                default:
3452
                    ret = -TARGET_EINVAL;
B
bellard 已提交
3453 3454
                    goto fail;
                }
3455 3456
                if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
                    goto efault;
3457 3458
                target_to_host_sigset(&set, p);
                unlock_user(p, arg2, 0);
B
bellard 已提交
3459 3460 3461 3462 3463 3464
                set_ptr = &set;
            } else {
                how = 0;
                set_ptr = NULL;
            }
            ret = get_errno(sigprocmask(how, set_ptr, &oldset));
3465
            if (!is_error(ret) && arg3) {
3466 3467
                if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
                    goto efault;
3468 3469
                host_to_target_sigset(p, &oldset);
                unlock_user(p, arg3, sizeof(target_sigset_t));
B
bellard 已提交
3470 3471 3472
            }
        }
        break;
3473
#ifdef TARGET_NR_sigpending
B
bellard 已提交
3474 3475 3476 3477 3478
    case TARGET_NR_sigpending:
        {
            sigset_t set;
            ret = get_errno(sigpending(&set));
            if (!is_error(ret)) {
3479 3480
                if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
                    goto efault;
3481 3482
                host_to_target_old_sigset(p, &set);
                unlock_user(p, arg1, sizeof(target_sigset_t));
B
bellard 已提交
3483 3484 3485
            }
        }
        break;
3486
#endif
B
bellard 已提交
3487 3488 3489 3490 3491
    case TARGET_NR_rt_sigpending:
        {
            sigset_t set;
            ret = get_errno(sigpending(&set));
            if (!is_error(ret)) {
3492 3493
                if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
                    goto efault;
3494 3495
                host_to_target_sigset(p, &set);
                unlock_user(p, arg1, sizeof(target_sigset_t));
B
bellard 已提交
3496 3497 3498
            }
        }
        break;
3499
#ifdef TARGET_NR_sigsuspend
B
bellard 已提交
3500 3501 3502
    case TARGET_NR_sigsuspend:
        {
            sigset_t set;
3503 3504
            if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
                goto efault;
3505 3506
            target_to_host_old_sigset(&set, p);
            unlock_user(p, arg1, 0);
B
bellard 已提交
3507 3508 3509
            ret = get_errno(sigsuspend(&set));
        }
        break;
3510
#endif
B
bellard 已提交
3511 3512 3513
    case TARGET_NR_rt_sigsuspend:
        {
            sigset_t set;
3514 3515
            if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
                goto efault;
3516 3517
            target_to_host_sigset(&set, p);
            unlock_user(p, arg1, 0);
B
bellard 已提交
3518 3519 3520 3521 3522 3523 3524 3525
            ret = get_errno(sigsuspend(&set));
        }
        break;
    case TARGET_NR_rt_sigtimedwait:
        {
            sigset_t set;
            struct timespec uts, *puts;
            siginfo_t uinfo;
3526

3527 3528
            if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
                goto efault;
3529 3530 3531
            target_to_host_sigset(&set, p);
            unlock_user(p, arg1, 0);
            if (arg3) {
B
bellard 已提交
3532
                puts = &uts;
3533
                target_to_host_timespec(puts, arg3);
B
bellard 已提交
3534 3535 3536 3537
            } else {
                puts = NULL;
            }
            ret = get_errno(sigtimedwait(&set, &uinfo, puts));
3538
            if (!is_error(ret) && arg2) {
3539 3540
                if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_sigset_t), 0)))
                    goto efault;
3541 3542
                host_to_target_siginfo(p, &uinfo);
                unlock_user(p, arg2, sizeof(target_sigset_t));
B
bellard 已提交
3543 3544 3545 3546 3547 3548
            }
        }
        break;
    case TARGET_NR_rt_sigqueueinfo:
        {
            siginfo_t uinfo;
3549 3550
            if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
                goto efault;
3551 3552
            target_to_host_siginfo(&uinfo, p);
            unlock_user(p, arg1, 0);
B
bellard 已提交
3553 3554 3555
            ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
        }
        break;
3556
#ifdef TARGET_NR_sigreturn
B
bellard 已提交
3557 3558 3559 3560
    case TARGET_NR_sigreturn:
        /* NOTE: ret is eax, so not transcoding must be done */
        ret = do_sigreturn(cpu_env);
        break;
3561
#endif
B
bellard 已提交
3562 3563 3564 3565
    case TARGET_NR_rt_sigreturn:
        /* NOTE: ret is eax, so not transcoding must be done */
        ret = do_rt_sigreturn(cpu_env);
        break;
3566
    case TARGET_NR_sethostname:
3567 3568
        if (!(p = lock_user_string(arg1)))
            goto efault;
3569 3570
        ret = get_errno(sethostname(p, arg2));
        unlock_user(p, arg1, 0);
3571 3572
        break;
    case TARGET_NR_setrlimit:
B
bellard 已提交
3573 3574 3575
        {
            /* XXX: convert resource ? */
            int resource = arg1;
3576
            struct target_rlimit *target_rlim;
B
bellard 已提交
3577
            struct rlimit rlim;
3578 3579
            if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
                goto efault;
B
bellard 已提交
3580 3581
            rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
            rlim.rlim_max = tswapl(target_rlim->rlim_max);
3582
            unlock_user_struct(target_rlim, arg2, 0);
B
bellard 已提交
3583 3584 3585
            ret = get_errno(setrlimit(resource, &rlim));
        }
        break;
3586
    case TARGET_NR_getrlimit:
B
bellard 已提交
3587 3588 3589
        {
            /* XXX: convert resource ? */
            int resource = arg1;
3590
            struct target_rlimit *target_rlim;
B
bellard 已提交
3591
            struct rlimit rlim;
3592

B
bellard 已提交
3593 3594
            ret = get_errno(getrlimit(resource, &rlim));
            if (!is_error(ret)) {
3595 3596
                if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
                    goto efault;
3597 3598 3599
                rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
                rlim.rlim_max = tswapl(target_rlim->rlim_max);
                unlock_user_struct(target_rlim, arg2, 1);
B
bellard 已提交
3600 3601 3602
            }
        }
        break;
3603
    case TARGET_NR_getrusage:
B
bellard 已提交
3604 3605 3606 3607
        {
            struct rusage rusage;
            ret = get_errno(getrusage(arg1, &rusage));
            if (!is_error(ret)) {
3608
                host_to_target_rusage(arg2, &rusage);
B
bellard 已提交
3609 3610 3611
            }
        }
        break;
3612 3613 3614 3615 3616
    case TARGET_NR_gettimeofday:
        {
            struct timeval tv;
            ret = get_errno(gettimeofday(&tv, NULL));
            if (!is_error(ret)) {
3617
                host_to_target_timeval(arg1, &tv);
3618 3619 3620 3621 3622 3623
            }
        }
        break;
    case TARGET_NR_settimeofday:
        {
            struct timeval tv;
3624
            target_to_host_timeval(&tv, arg1);
3625 3626 3627
            ret = get_errno(settimeofday(&tv, NULL));
        }
        break;
B
bellard 已提交
3628
#ifdef TARGET_NR_select
3629
    case TARGET_NR_select:
B
bellard 已提交
3630
        {
3631
            struct target_sel_arg_struct *sel;
3632
            abi_ulong inp, outp, exp, tvp;
3633 3634
            long nsel;

3635 3636
            if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
                goto efault;
3637 3638 3639 3640 3641 3642 3643
            nsel = tswapl(sel->n);
            inp = tswapl(sel->inp);
            outp = tswapl(sel->outp);
            exp = tswapl(sel->exp);
            tvp = tswapl(sel->tvp);
            unlock_user_struct(sel, arg1, 0);
            ret = do_select(nsel, inp, outp, exp, tvp);
B
bellard 已提交
3644 3645
        }
        break;
B
bellard 已提交
3646
#endif
3647
    case TARGET_NR_symlink:
3648 3649 3650 3651
        {
            void *p2;
            p = lock_user_string(arg1);
            p2 = lock_user_string(arg2);
3652 3653 3654 3655
            if (!p || !p2)
                ret = -TARGET_EFAULT;
            else
                ret = get_errno(symlink(p, p2));
3656 3657 3658
            unlock_user(p2, arg2, 0);
            unlock_user(p, arg1, 0);
        }
3659
        break;
3660 3661 3662
#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
    case TARGET_NR_symlinkat:
        {
3663
            void *p2;
3664 3665
            p  = lock_user_string(arg1);
            p2 = lock_user_string(arg3);
3666
            if (!p || !p2)
3667
                ret = -TARGET_EFAULT;
3668 3669
            else
                ret = get_errno(sys_symlinkat(p, arg2, p2));
3670 3671
            unlock_user(p2, arg3, 0);
            unlock_user(p, arg1, 0);
3672 3673 3674
        }
        break;
#endif
3675
#ifdef TARGET_NR_oldlstat
3676 3677
    case TARGET_NR_oldlstat:
        goto unimplemented;
3678
#endif
3679
    case TARGET_NR_readlink:
3680 3681 3682
        {
            void *p2;
            p = lock_user_string(arg1);
3683 3684 3685 3686 3687
            p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
            if (!p || !p2)
                ret = -TARGET_EFAULT;
            else
                ret = get_errno(readlink(path(p), p2, arg3));
3688 3689 3690
            unlock_user(p2, arg2, ret);
            unlock_user(p, arg1, 0);
        }
3691
        break;
3692 3693 3694
#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
    case TARGET_NR_readlinkat:
        {
3695
            void *p2;
3696
            p  = lock_user_string(arg2);
3697 3698
            p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
            if (!p || !p2)
3699
        	ret = -TARGET_EFAULT;
3700 3701
            else
                ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
3702 3703
            unlock_user(p2, arg3, ret);
            unlock_user(p, arg2, 0);
3704 3705 3706
        }
        break;
#endif
3707
#ifdef TARGET_NR_uselib
3708 3709
    case TARGET_NR_uselib:
        goto unimplemented;
3710 3711
#endif
#ifdef TARGET_NR_swapon
3712
    case TARGET_NR_swapon:
3713 3714
        if (!(p = lock_user_string(arg1)))
            goto efault;
3715 3716
        ret = get_errno(swapon(p, arg2));
        unlock_user(p, arg1, 0);
3717
        break;
3718
#endif
3719 3720
    case TARGET_NR_reboot:
        goto unimplemented;
3721
#ifdef TARGET_NR_readdir
3722 3723
    case TARGET_NR_readdir:
        goto unimplemented;
3724 3725
#endif
#ifdef TARGET_NR_mmap
3726
    case TARGET_NR_mmap:
3727
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS)
3728
        {
3729 3730
            abi_ulong *v;
            abi_ulong v1, v2, v3, v4, v5, v6;
3731 3732
            if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
                goto efault;
3733 3734 3735 3736 3737 3738 3739
            v1 = tswapl(v[0]);
            v2 = tswapl(v[1]);
            v3 = tswapl(v[2]);
            v4 = tswapl(v[3]);
            v5 = tswapl(v[4]);
            v6 = tswapl(v[5]);
            unlock_user(v, arg1, 0);
3740
            ret = get_errno(target_mmap(v1, v2, v3,
B
bellard 已提交
3741 3742
                                        target_to_host_bitmask(v4, mmap_flags_tbl),
                                        v5, v6));
3743 3744
        }
#else
3745 3746
        ret = get_errno(target_mmap(arg1, arg2, arg3,
                                    target_to_host_bitmask(arg4, mmap_flags_tbl),
B
bellard 已提交
3747 3748
                                    arg5,
                                    arg6));
3749
#endif
B
bellard 已提交
3750
        break;
3751
#endif
B
bellard 已提交
3752
#ifdef TARGET_NR_mmap2
B
bellard 已提交
3753
    case TARGET_NR_mmap2:
T
ths 已提交
3754
#if defined(TARGET_SPARC) || defined(TARGET_MIPS)
B
bellard 已提交
3755 3756 3757 3758
#define MMAP_SHIFT 12
#else
#define MMAP_SHIFT TARGET_PAGE_BITS
#endif
3759 3760
        ret = get_errno(target_mmap(arg1, arg2, arg3,
                                    target_to_host_bitmask(arg4, mmap_flags_tbl),
B
bellard 已提交
3761
                                    arg5,
B
bellard 已提交
3762
                                    arg6 << MMAP_SHIFT));
3763
        break;
B
bellard 已提交
3764
#endif
3765
    case TARGET_NR_munmap:
B
bellard 已提交
3766
        ret = get_errno(target_munmap(arg1, arg2));
3767
        break;
B
bellard 已提交
3768
    case TARGET_NR_mprotect:
B
bellard 已提交
3769
        ret = get_errno(target_mprotect(arg1, arg2, arg3));
B
bellard 已提交
3770
        break;
3771
#ifdef TARGET_NR_mremap
B
bellard 已提交
3772
    case TARGET_NR_mremap:
B
bellard 已提交
3773
        ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
B
bellard 已提交
3774
        break;
3775
#endif
3776
        /* ??? msync/mlock/munlock are broken for softmmu.  */
3777
#ifdef TARGET_NR_msync
B
bellard 已提交
3778
    case TARGET_NR_msync:
3779
        ret = get_errno(msync(g2h(arg1), arg2, arg3));
B
bellard 已提交
3780
        break;
3781 3782
#endif
#ifdef TARGET_NR_mlock
B
bellard 已提交
3783
    case TARGET_NR_mlock:
3784
        ret = get_errno(mlock(g2h(arg1), arg2));
B
bellard 已提交
3785
        break;
3786 3787
#endif
#ifdef TARGET_NR_munlock
B
bellard 已提交
3788
    case TARGET_NR_munlock:
3789
        ret = get_errno(munlock(g2h(arg1), arg2));
B
bellard 已提交
3790
        break;
3791 3792
#endif
#ifdef TARGET_NR_mlockall
B
bellard 已提交
3793 3794 3795
    case TARGET_NR_mlockall:
        ret = get_errno(mlockall(arg1));
        break;
3796 3797
#endif
#ifdef TARGET_NR_munlockall
B
bellard 已提交
3798 3799 3800
    case TARGET_NR_munlockall:
        ret = get_errno(munlockall());
        break;
3801
#endif
3802
    case TARGET_NR_truncate:
3803 3804
        if (!(p = lock_user_string(arg1)))
            goto efault;
3805 3806
        ret = get_errno(truncate(p, arg2));
        unlock_user(p, arg1, 0);
3807 3808 3809 3810 3811 3812 3813
        break;
    case TARGET_NR_ftruncate:
        ret = get_errno(ftruncate(arg1, arg2));
        break;
    case TARGET_NR_fchmod:
        ret = get_errno(fchmod(arg1, arg2));
        break;
3814 3815
#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
    case TARGET_NR_fchmodat:
3816 3817 3818 3819
        if (!(p = lock_user_string(arg2)))
            goto efault;
        ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
        unlock_user(p, arg2, 0);
3820 3821
        break;
#endif
3822
    case TARGET_NR_getpriority:
3823 3824 3825 3826
        /* libc does special remapping of the return value of
         * sys_getpriority() so it's just easiest to call
         * sys_getpriority() directly rather than through libc. */
        ret = sys_getpriority(arg1, arg2);
3827 3828 3829 3830
        break;
    case TARGET_NR_setpriority:
        ret = get_errno(setpriority(arg1, arg2, arg3));
        break;
3831
#ifdef TARGET_NR_profil
3832 3833
    case TARGET_NR_profil:
        goto unimplemented;
3834
#endif
3835
    case TARGET_NR_statfs:
3836 3837
        if (!(p = lock_user_string(arg1)))
            goto efault;
3838 3839
        ret = get_errno(statfs(path(p), &stfs));
        unlock_user(p, arg1, 0);
3840 3841
    convert_statfs:
        if (!is_error(ret)) {
3842
            struct target_statfs *target_stfs;
3843

3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855
            if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
                goto efault;
            __put_user(stfs.f_type, &target_stfs->f_type);
            __put_user(stfs.f_bsize, &target_stfs->f_bsize);
            __put_user(stfs.f_blocks, &target_stfs->f_blocks);
            __put_user(stfs.f_bfree, &target_stfs->f_bfree);
            __put_user(stfs.f_bavail, &target_stfs->f_bavail);
            __put_user(stfs.f_files, &target_stfs->f_files);
            __put_user(stfs.f_ffree, &target_stfs->f_ffree);
            __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
            __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
            __put_user(stfs.f_namelen, &target_stfs->f_namelen);
3856
            unlock_user_struct(target_stfs, arg2, 1);
3857 3858 3859
        }
        break;
    case TARGET_NR_fstatfs:
B
bellard 已提交
3860
        ret = get_errno(fstatfs(arg1, &stfs));
3861
        goto convert_statfs;
B
bellard 已提交
3862 3863
#ifdef TARGET_NR_statfs64
    case TARGET_NR_statfs64:
3864 3865
        if (!(p = lock_user_string(arg1)))
            goto efault;
3866 3867
        ret = get_errno(statfs(path(p), &stfs));
        unlock_user(p, arg1, 0);
B
bellard 已提交
3868 3869
    convert_statfs64:
        if (!is_error(ret)) {
3870
            struct target_statfs64 *target_stfs;
3871

3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884
            if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
                goto efault;
            __put_user(stfs.f_type, &target_stfs->f_type);
            __put_user(stfs.f_bsize, &target_stfs->f_bsize);
            __put_user(stfs.f_blocks, &target_stfs->f_blocks);
            __put_user(stfs.f_bfree, &target_stfs->f_bfree);
            __put_user(stfs.f_bavail, &target_stfs->f_bavail);
            __put_user(stfs.f_files, &target_stfs->f_files);
            __put_user(stfs.f_ffree, &target_stfs->f_ffree);
            __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
            __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
            __put_user(stfs.f_namelen, &target_stfs->f_namelen);
            unlock_user_struct(target_stfs, arg3, 1);
B
bellard 已提交
3885 3886 3887 3888 3889 3890
        }
        break;
    case TARGET_NR_fstatfs64:
        ret = get_errno(fstatfs(arg1, &stfs));
        goto convert_statfs64;
#endif
3891
#ifdef TARGET_NR_ioperm
3892 3893
    case TARGET_NR_ioperm:
        goto unimplemented;
3894
#endif
3895
#ifdef TARGET_NR_socketcall
3896
    case TARGET_NR_socketcall:
3897
        ret = do_socketcall(arg1, arg2);
3898
        break;
3899
#endif
3900 3901
#ifdef TARGET_NR_accept
    case TARGET_NR_accept:
P
pbrook 已提交
3902
        ret = do_accept(arg1, arg2, arg3);
3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916
        break;
#endif
#ifdef TARGET_NR_bind
    case TARGET_NR_bind:
        ret = do_bind(arg1, arg2, arg3);
        break;
#endif
#ifdef TARGET_NR_connect
    case TARGET_NR_connect:
        ret = do_connect(arg1, arg2, arg3);
        break;
#endif
#ifdef TARGET_NR_getpeername
    case TARGET_NR_getpeername:
P
pbrook 已提交
3917
        ret = do_getpeername(arg1, arg2, arg3);
3918 3919 3920 3921
        break;
#endif
#ifdef TARGET_NR_getsockname
    case TARGET_NR_getsockname:
P
pbrook 已提交
3922
        ret = do_getsockname(arg1, arg2, arg3);
3923 3924 3925 3926 3927 3928 3929 3930 3931
        break;
#endif
#ifdef TARGET_NR_getsockopt
    case TARGET_NR_getsockopt:
        ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
        break;
#endif
#ifdef TARGET_NR_listen
    case TARGET_NR_listen:
P
pbrook 已提交
3932
        ret = get_errno(listen(arg1, arg2));
3933 3934 3935 3936
        break;
#endif
#ifdef TARGET_NR_recv
    case TARGET_NR_recv:
P
pbrook 已提交
3937
        ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
3938 3939 3940 3941
        break;
#endif
#ifdef TARGET_NR_recvfrom
    case TARGET_NR_recvfrom:
P
pbrook 已提交
3942
        ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
3943 3944 3945 3946 3947 3948 3949 3950 3951
        break;
#endif
#ifdef TARGET_NR_recvmsg
    case TARGET_NR_recvmsg:
        ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
        break;
#endif
#ifdef TARGET_NR_send
    case TARGET_NR_send:
P
pbrook 已提交
3952
        ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
3953 3954 3955 3956 3957 3958 3959 3960 3961
        break;
#endif
#ifdef TARGET_NR_sendmsg
    case TARGET_NR_sendmsg:
        ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
        break;
#endif
#ifdef TARGET_NR_sendto
    case TARGET_NR_sendto:
P
pbrook 已提交
3962
        ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
3963 3964 3965 3966
        break;
#endif
#ifdef TARGET_NR_shutdown
    case TARGET_NR_shutdown:
P
pbrook 已提交
3967
        ret = get_errno(shutdown(arg1, arg2));
3968 3969 3970 3971 3972 3973 3974 3975 3976
        break;
#endif
#ifdef TARGET_NR_socket
    case TARGET_NR_socket:
        ret = do_socket(arg1, arg2, arg3);
        break;
#endif
#ifdef TARGET_NR_socketpair
    case TARGET_NR_socketpair:
P
pbrook 已提交
3977
        ret = do_socketpair(arg1, arg2, arg3, arg4);
3978 3979 3980 3981 3982 3983 3984
        break;
#endif
#ifdef TARGET_NR_setsockopt
    case TARGET_NR_setsockopt:
        ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
        break;
#endif
3985

3986
    case TARGET_NR_syslog:
3987 3988
        if (!(p = lock_user_string(arg2)))
            goto efault;
3989 3990
        ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
        unlock_user(p, arg2, 0);
3991 3992
        break;

3993
    case TARGET_NR_setitimer:
B
bellard 已提交
3994 3995 3996
        {
            struct itimerval value, ovalue, *pvalue;

3997
            if (arg2) {
B
bellard 已提交
3998
                pvalue = &value;
3999
                target_to_host_timeval(&pvalue->it_interval,
4000
                                       arg2);
4001
                target_to_host_timeval(&pvalue->it_value,
4002
                                       arg2 + sizeof(struct target_timeval));
B
bellard 已提交
4003 4004 4005 4006
            } else {
                pvalue = NULL;
            }
            ret = get_errno(setitimer(arg1, pvalue, &ovalue));
4007 4008
            if (!is_error(ret) && arg3) {
                host_to_target_timeval(arg3,
B
bellard 已提交
4009
                                       &ovalue.it_interval);
4010
                host_to_target_timeval(arg3 + sizeof(struct target_timeval),
B
bellard 已提交
4011 4012 4013 4014
                                       &ovalue.it_value);
            }
        }
        break;
4015
    case TARGET_NR_getitimer:
B
bellard 已提交
4016 4017
        {
            struct itimerval value;
4018

B
bellard 已提交
4019
            ret = get_errno(getitimer(arg1, &value));
4020 4021
            if (!is_error(ret) && arg2) {
                host_to_target_timeval(arg2,
B
bellard 已提交
4022
                                       &value.it_interval);
4023
                host_to_target_timeval(arg2 + sizeof(struct target_timeval),
B
bellard 已提交
4024 4025 4026 4027
                                       &value.it_value);
            }
        }
        break;
4028
    case TARGET_NR_stat:
4029 4030
        if (!(p = lock_user_string(arg1)))
            goto efault;
4031 4032
        ret = get_errno(stat(path(p), &st));
        unlock_user(p, arg1, 0);
4033 4034
        goto do_stat;
    case TARGET_NR_lstat:
4035 4036
        if (!(p = lock_user_string(arg1)))
            goto efault;
4037 4038
        ret = get_errno(lstat(path(p), &st));
        unlock_user(p, arg1, 0);
4039 4040 4041 4042 4043 4044
        goto do_stat;
    case TARGET_NR_fstat:
        {
            ret = get_errno(fstat(arg1, &st));
        do_stat:
            if (!is_error(ret)) {
4045
                struct target_stat *target_st;
4046

4047 4048
                if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
                    goto efault;
4049
#if defined(TARGET_MIPS) || (defined(TARGET_SPARC64) && !defined(TARGET_ABI32))
4050 4051
                target_st->st_dev = tswap32(st.st_dev);
#else
4052
                target_st->st_dev = tswap16(st.st_dev);
4053
#endif
4054
                target_st->st_ino = tswapl(st.st_ino);
4055
#if defined(TARGET_PPC) || defined(TARGET_MIPS)
4056 4057 4058
                target_st->st_mode = tswapl(st.st_mode); /* XXX: check this */
                target_st->st_uid = tswap32(st.st_uid);
                target_st->st_gid = tswap32(st.st_gid);
4059
#elif defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
B
blueswir1 已提交
4060 4061 4062
                target_st->st_mode = tswap32(st.st_mode);
                target_st->st_uid = tswap32(st.st_uid);
                target_st->st_gid = tswap32(st.st_gid);
4063
#else
4064
                target_st->st_mode = tswap16(st.st_mode);
4065 4066
                target_st->st_uid = tswap16(st.st_uid);
                target_st->st_gid = tswap16(st.st_gid);
4067
#endif
4068 4069 4070 4071
#if defined(TARGET_MIPS)
		/* If this is the same on PPC, then just merge w/ the above ifdef */
                target_st->st_nlink = tswapl(st.st_nlink);
                target_st->st_rdev = tswapl(st.st_rdev);
4072
#elif defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
B
blueswir1 已提交
4073 4074
                target_st->st_nlink = tswap32(st.st_nlink);
                target_st->st_rdev = tswap32(st.st_rdev);
4075
#else
4076
                target_st->st_nlink = tswap16(st.st_nlink);
4077
                target_st->st_rdev = tswap16(st.st_rdev);
4078
#endif
4079 4080 4081
                target_st->st_size = tswapl(st.st_size);
                target_st->st_blksize = tswapl(st.st_blksize);
                target_st->st_blocks = tswapl(st.st_blocks);
B
bellard 已提交
4082 4083 4084
                target_st->target_st_atime = tswapl(st.st_atime);
                target_st->target_st_mtime = tswapl(st.st_mtime);
                target_st->target_st_ctime = tswapl(st.st_ctime);
4085
                unlock_user_struct(target_st, arg2, 1);
4086 4087 4088
            }
        }
        break;
4089
#ifdef TARGET_NR_olduname
4090 4091
    case TARGET_NR_olduname:
        goto unimplemented;
4092 4093
#endif
#ifdef TARGET_NR_iopl
4094 4095
    case TARGET_NR_iopl:
        goto unimplemented;
4096
#endif
4097 4098 4099
    case TARGET_NR_vhangup:
        ret = get_errno(vhangup());
        break;
4100
#ifdef TARGET_NR_idle
4101 4102
    case TARGET_NR_idle:
        goto unimplemented;
B
bellard 已提交
4103 4104 4105 4106 4107
#endif
#ifdef TARGET_NR_syscall
    case TARGET_NR_syscall:
    	ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
    	break;
4108
#endif
4109 4110 4111
    case TARGET_NR_wait4:
        {
            int status;
4112
            abi_long status_ptr = arg2;
4113
            struct rusage rusage, *rusage_ptr;
4114
            abi_ulong target_rusage = arg4;
4115 4116 4117 4118 4119 4120 4121
            if (target_rusage)
                rusage_ptr = &rusage;
            else
                rusage_ptr = NULL;
            ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
            if (!is_error(ret)) {
                if (status_ptr)
4122
                    tputl(status_ptr, status);
4123
                if (target_rusage) {
B
bellard 已提交
4124
                    host_to_target_rusage(target_rusage, &rusage);
4125 4126 4127 4128
                }
            }
        }
        break;
4129
#ifdef TARGET_NR_swapoff
4130
    case TARGET_NR_swapoff:
4131 4132
        if (!(p = lock_user_string(arg1)))
            goto efault;
4133 4134
        ret = get_errno(swapoff(p));
        unlock_user(p, arg1, 0);
4135
        break;
4136
#endif
4137
    case TARGET_NR_sysinfo:
B
bellard 已提交
4138
        {
4139
            struct target_sysinfo *target_value;
B
bellard 已提交
4140 4141
            struct sysinfo value;
            ret = get_errno(sysinfo(&value));
4142
            if (!is_error(ret) && arg1)
B
bellard 已提交
4143
            {
4144 4145
                if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
                    goto efault;
B
bellard 已提交
4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159
                __put_user(value.uptime, &target_value->uptime);
                __put_user(value.loads[0], &target_value->loads[0]);
                __put_user(value.loads[1], &target_value->loads[1]);
                __put_user(value.loads[2], &target_value->loads[2]);
                __put_user(value.totalram, &target_value->totalram);
                __put_user(value.freeram, &target_value->freeram);
                __put_user(value.sharedram, &target_value->sharedram);
                __put_user(value.bufferram, &target_value->bufferram);
                __put_user(value.totalswap, &target_value->totalswap);
                __put_user(value.freeswap, &target_value->freeswap);
                __put_user(value.procs, &target_value->procs);
                __put_user(value.totalhigh, &target_value->totalhigh);
                __put_user(value.freehigh, &target_value->freehigh);
                __put_user(value.mem_unit, &target_value->mem_unit);
4160
                unlock_user_struct(target_value, arg1, 1);
B
bellard 已提交
4161 4162 4163
            }
        }
        break;
4164
#ifdef TARGET_NR_ipc
4165
    case TARGET_NR_ipc:
4166 4167
	ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
	break;
4168
#endif
4169 4170 4171 4172
    case TARGET_NR_fsync:
        ret = get_errno(fsync(arg1));
        break;
    case TARGET_NR_clone:
B
bellard 已提交
4173 4174
        ret = get_errno(do_fork(cpu_env, arg1, arg2));
        break;
4175 4176 4177
#ifdef __NR_exit_group
        /* new thread calls */
    case TARGET_NR_exit_group:
4178
        gdb_exit(cpu_env, arg1);
4179 4180 4181
        ret = get_errno(exit_group(arg1));
        break;
#endif
4182
    case TARGET_NR_setdomainname:
4183 4184
        if (!(p = lock_user_string(arg1)))
            goto efault;
4185 4186
        ret = get_errno(setdomainname(p, arg2));
        unlock_user(p, arg1, 0);
4187 4188 4189
        break;
    case TARGET_NR_uname:
        /* no need to transcode because we use the linux syscall */
B
bellard 已提交
4190 4191
        {
            struct new_utsname * buf;
4192

4193 4194
            if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
                goto efault;
B
bellard 已提交
4195 4196 4197 4198 4199
            ret = get_errno(sys_uname(buf));
            if (!is_error(ret)) {
                /* Overrite the native machine name with whatever is being
                   emulated. */
                strcpy (buf->machine, UNAME_MACHINE);
4200 4201 4202
                /* Allow the user to override the reported release.  */
                if (qemu_uname_release && *qemu_uname_release)
                  strcpy (buf->release, qemu_uname_release);
B
bellard 已提交
4203
            }
4204
            unlock_user_struct(buf, arg1, 1);
B
bellard 已提交
4205
        }
4206
        break;
B
bellard 已提交
4207
#ifdef TARGET_I386
4208
    case TARGET_NR_modify_ldt:
4209
        ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
B
bellard 已提交
4210
        break;
4211
#if !defined(TARGET_X86_64)
B
bellard 已提交
4212 4213 4214
    case TARGET_NR_vm86old:
        goto unimplemented;
    case TARGET_NR_vm86:
4215
        ret = do_vm86(cpu_env, arg1, arg2);
B
bellard 已提交
4216
        break;
4217
#endif
B
bellard 已提交
4218
#endif
4219 4220
    case TARGET_NR_adjtimex:
        goto unimplemented;
4221
#ifdef TARGET_NR_create_module
4222
    case TARGET_NR_create_module:
4223
#endif
4224 4225
    case TARGET_NR_init_module:
    case TARGET_NR_delete_module:
4226
#ifdef TARGET_NR_get_kernel_syms
4227
    case TARGET_NR_get_kernel_syms:
4228
#endif
4229 4230 4231 4232 4233 4234 4235 4236 4237
        goto unimplemented;
    case TARGET_NR_quotactl:
        goto unimplemented;
    case TARGET_NR_getpgid:
        ret = get_errno(getpgid(arg1));
        break;
    case TARGET_NR_fchdir:
        ret = get_errno(fchdir(arg1));
        break;
4238
#ifdef TARGET_NR_bdflush /* not on x86_64 */
4239 4240
    case TARGET_NR_bdflush:
        goto unimplemented;
4241
#endif
4242
#ifdef TARGET_NR_sysfs
4243 4244
    case TARGET_NR_sysfs:
        goto unimplemented;
4245
#endif
4246
    case TARGET_NR_personality:
B
bellard 已提交
4247
        ret = get_errno(personality(arg1));
4248
        break;
4249
#ifdef TARGET_NR_afs_syscall
4250 4251
    case TARGET_NR_afs_syscall:
        goto unimplemented;
4252
#endif
4253
#ifdef TARGET_NR__llseek /* Not on alpha */
4254 4255
    case TARGET_NR__llseek:
        {
B
bellard 已提交
4256 4257
#if defined (__x86_64__)
            ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
4258
            tput64(arg4, ret);
B
bellard 已提交
4259
#else
4260 4261
            int64_t res;
            ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
4262
            tput64(arg4, res);
B
bellard 已提交
4263
#endif
4264 4265
        }
        break;
4266
#endif
4267
    case TARGET_NR_getdents:
4268
#if TARGET_ABI_BITS != 32
4269
        goto unimplemented;
4270
#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
B
bellard 已提交
4271
        {
4272
            struct target_dirent *target_dirp;
B
bellard 已提交
4273
            struct dirent *dirp;
4274
            abi_long count = arg3;
B
bellard 已提交
4275 4276

	    dirp = malloc(count);
4277
	    if (!dirp) {
4278
                ret = -TARGET_ENOMEM;
4279 4280
                goto fail;
            }
4281

B
bellard 已提交
4282 4283 4284 4285 4286 4287 4288 4289 4290 4291
            ret = get_errno(sys_getdents(arg1, dirp, count));
            if (!is_error(ret)) {
                struct dirent *de;
		struct target_dirent *tde;
                int len = ret;
                int reclen, treclen;
		int count1, tnamelen;

		count1 = 0;
                de = dirp;
4292 4293
                if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
                    goto efault;
B
bellard 已提交
4294 4295 4296
		tde = target_dirp;
                while (len > 0) {
                    reclen = de->d_reclen;
4297
		    treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
B
bellard 已提交
4298 4299 4300
                    tde->d_reclen = tswap16(treclen);
                    tde->d_ino = tswapl(de->d_ino);
                    tde->d_off = tswapl(de->d_off);
4301
		    tnamelen = treclen - (2 * sizeof(abi_long) + 2);
B
bellard 已提交
4302 4303
		    if (tnamelen > 256)
                        tnamelen = 256;
B
bellard 已提交
4304
                    /* XXX: may not be correct */
B
bellard 已提交
4305 4306 4307
		    strncpy(tde->d_name, de->d_name, tnamelen);
                    de = (struct dirent *)((char *)de + reclen);
                    len -= reclen;
J
j_mayer 已提交
4308
                    tde = (struct target_dirent *)((char *)tde + treclen);
B
bellard 已提交
4309 4310 4311
		    count1 += treclen;
                }
		ret = count1;
4312
                unlock_user(target_dirp, arg2, ret);
B
bellard 已提交
4313 4314 4315 4316
            }
	    free(dirp);
        }
#else
4317
        {
4318
            struct dirent *dirp;
4319
            abi_long count = arg3;
B
bellard 已提交
4320

4321 4322
            if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
                goto efault;
B
bellard 已提交
4323
            ret = get_errno(sys_getdents(arg1, dirp, count));
4324 4325 4326 4327 4328 4329
            if (!is_error(ret)) {
                struct dirent *de;
                int len = ret;
                int reclen;
                de = dirp;
                while (len > 0) {
B
bellard 已提交
4330
                    reclen = de->d_reclen;
4331 4332
                    if (reclen > len)
                        break;
B
bellard 已提交
4333
                    de->d_reclen = tswap16(reclen);
4334 4335 4336 4337 4338 4339
                    tswapls(&de->d_ino);
                    tswapls(&de->d_off);
                    de = (struct dirent *)((char *)de + reclen);
                    len -= reclen;
                }
            }
4340
            unlock_user(dirp, arg2, ret);
4341
        }
B
bellard 已提交
4342
#endif
4343
        break;
T
ths 已提交
4344
#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
B
bellard 已提交
4345 4346
    case TARGET_NR_getdents64:
        {
4347
            struct dirent64 *dirp;
4348
            abi_long count = arg3;
4349 4350
            if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
                goto efault;
B
bellard 已提交
4351 4352 4353 4354 4355 4356 4357
            ret = get_errno(sys_getdents64(arg1, dirp, count));
            if (!is_error(ret)) {
                struct dirent64 *de;
                int len = ret;
                int reclen;
                de = dirp;
                while (len > 0) {
B
bellard 已提交
4358
                    reclen = de->d_reclen;
B
bellard 已提交
4359 4360
                    if (reclen > len)
                        break;
B
bellard 已提交
4361
                    de->d_reclen = tswap16(reclen);
B
bellard 已提交
4362 4363
                    tswap64s((uint64_t *)&de->d_ino);
                    tswap64s((uint64_t *)&de->d_off);
B
bellard 已提交
4364 4365 4366 4367
                    de = (struct dirent64 *)((char *)de + reclen);
                    len -= reclen;
                }
            }
4368
            unlock_user(dirp, arg2, ret);
B
bellard 已提交
4369 4370
        }
        break;
4371
#endif /* TARGET_NR_getdents64 */
4372
#ifdef TARGET_NR__newselect
4373
    case TARGET_NR__newselect:
4374
        ret = do_select(arg1, arg2, arg3, arg4, arg5);
4375
        break;
4376 4377
#endif
#ifdef TARGET_NR_poll
B
bellard 已提交
4378 4379
    case TARGET_NR_poll:
        {
4380
            struct target_pollfd *target_pfd;
B
bellard 已提交
4381 4382 4383
            unsigned int nfds = arg2;
            int timeout = arg3;
            struct pollfd *pfd;
B
bellard 已提交
4384
            unsigned int i;
B
bellard 已提交
4385

4386 4387 4388
            target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
            if (!target_pfd)
                goto efault;
B
bellard 已提交
4389 4390
            pfd = alloca(sizeof(struct pollfd) * nfds);
            for(i = 0; i < nfds; i++) {
B
bellard 已提交
4391 4392
                pfd[i].fd = tswap32(target_pfd[i].fd);
                pfd[i].events = tswap16(target_pfd[i].events);
B
bellard 已提交
4393 4394 4395 4396
            }
            ret = get_errno(poll(pfd, nfds, timeout));
            if (!is_error(ret)) {
                for(i = 0; i < nfds; i++) {
B
bellard 已提交
4397
                    target_pfd[i].revents = tswap16(pfd[i].revents);
B
bellard 已提交
4398
                }
4399 4400
                ret += nfds * (sizeof(struct target_pollfd)
                               - sizeof(struct pollfd));
B
bellard 已提交
4401
            }
4402
            unlock_user(target_pfd, arg1, ret);
B
bellard 已提交
4403 4404
        }
        break;
4405
#endif
4406
    case TARGET_NR_flock:
B
bellard 已提交
4407 4408 4409
        /* NOTE: the flock constant seems to be the same for every
           Linux platform */
        ret = get_errno(flock(arg1, arg2));
4410 4411 4412 4413 4414 4415 4416
        break;
    case TARGET_NR_readv:
        {
            int count = arg3;
            struct iovec *vec;

            vec = alloca(count * sizeof(struct iovec));
4417
            lock_iovec(VERIFY_WRITE, vec, arg2, count, 0);
4418
            ret = get_errno(readv(arg1, vec, count));
4419
            unlock_iovec(vec, arg2, count, 1);
4420 4421 4422 4423 4424 4425 4426 4427
        }
        break;
    case TARGET_NR_writev:
        {
            int count = arg3;
            struct iovec *vec;

            vec = alloca(count * sizeof(struct iovec));
4428
            lock_iovec(VERIFY_READ, vec, arg2, count, 1);
4429
            ret = get_errno(writev(arg1, vec, count));
4430
            unlock_iovec(vec, arg2, count, 0);
4431 4432 4433 4434 4435
        }
        break;
    case TARGET_NR_getsid:
        ret = get_errno(getsid(arg1));
        break;
4436
#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
4437
    case TARGET_NR_fdatasync:
B
bellard 已提交
4438 4439
        ret = get_errno(fdatasync(arg1));
        break;
4440
#endif
4441
    case TARGET_NR__sysctl:
4442
        /* We don't implement this, but ENOTDIR is always a safe
B
bellard 已提交
4443
           return value. */
4444 4445
        ret = -TARGET_ENOTDIR;
        break;
4446
    case TARGET_NR_sched_setparam:
B
bellard 已提交
4447
        {
4448
            struct sched_param *target_schp;
B
bellard 已提交
4449
            struct sched_param schp;
4450

4451 4452
            if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
                goto efault;
B
bellard 已提交
4453
            schp.sched_priority = tswap32(target_schp->sched_priority);
4454
            unlock_user_struct(target_schp, arg2, 0);
B
bellard 已提交
4455 4456 4457
            ret = get_errno(sched_setparam(arg1, &schp));
        }
        break;
4458
    case TARGET_NR_sched_getparam:
B
bellard 已提交
4459
        {
4460
            struct sched_param *target_schp;
B
bellard 已提交
4461 4462 4463
            struct sched_param schp;
            ret = get_errno(sched_getparam(arg1, &schp));
            if (!is_error(ret)) {
4464 4465
                if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
                    goto efault;
B
bellard 已提交
4466
                target_schp->sched_priority = tswap32(schp.sched_priority);
4467
                unlock_user_struct(target_schp, arg2, 1);
B
bellard 已提交
4468 4469 4470
            }
        }
        break;
4471
    case TARGET_NR_sched_setscheduler:
B
bellard 已提交
4472
        {
4473
            struct sched_param *target_schp;
B
bellard 已提交
4474
            struct sched_param schp;
4475 4476
            if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
                goto efault;
B
bellard 已提交
4477
            schp.sched_priority = tswap32(target_schp->sched_priority);
4478
            unlock_user_struct(target_schp, arg3, 0);
B
bellard 已提交
4479 4480 4481
            ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
        }
        break;
4482
    case TARGET_NR_sched_getscheduler:
B
bellard 已提交
4483 4484
        ret = get_errno(sched_getscheduler(arg1));
        break;
4485 4486 4487 4488
    case TARGET_NR_sched_yield:
        ret = get_errno(sched_yield());
        break;
    case TARGET_NR_sched_get_priority_max:
B
bellard 已提交
4489 4490
        ret = get_errno(sched_get_priority_max(arg1));
        break;
4491
    case TARGET_NR_sched_get_priority_min:
B
bellard 已提交
4492 4493
        ret = get_errno(sched_get_priority_min(arg1));
        break;
4494
    case TARGET_NR_sched_rr_get_interval:
B
bellard 已提交
4495 4496 4497 4498
        {
            struct timespec ts;
            ret = get_errno(sched_rr_get_interval(arg1, &ts));
            if (!is_error(ret)) {
4499
                host_to_target_timespec(arg2, &ts);
B
bellard 已提交
4500 4501 4502
            }
        }
        break;
4503
    case TARGET_NR_nanosleep:
B
bellard 已提交
4504 4505
        {
            struct timespec req, rem;
4506
            target_to_host_timespec(&req, arg1);
B
bellard 已提交
4507
            ret = get_errno(nanosleep(&req, &rem));
4508 4509
            if (is_error(ret) && arg2) {
                host_to_target_timespec(arg2, &rem);
B
bellard 已提交
4510 4511 4512
            }
        }
        break;
4513
#ifdef TARGET_NR_query_module
4514
    case TARGET_NR_query_module:
B
bellard 已提交
4515
        goto unimplemented;
4516 4517
#endif
#ifdef TARGET_NR_nfsservctl
4518
    case TARGET_NR_nfsservctl:
B
bellard 已提交
4519
        goto unimplemented;
4520
#endif
4521
    case TARGET_NR_prctl:
4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535
        switch (arg1)
            {
            case PR_GET_PDEATHSIG:
                {
                    int deathsig;
                    ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
                    if (!is_error(ret) && arg2)
                        tput32(arg2, deathsig);
                }
                break;
            default:
                ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
                break;
            }
4536
        break;
4537
#ifdef TARGET_NR_pread
4538
    case TARGET_NR_pread:
4539 4540
        if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
            goto efault;
4541 4542
        ret = get_errno(pread(arg1, p, arg3, arg4));
        unlock_user(p, arg2, ret);
4543
        break;
4544
    case TARGET_NR_pwrite:
4545 4546
        if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
            goto efault;
4547 4548
        ret = get_errno(pwrite(arg1, p, arg3, arg4));
        unlock_user(p, arg2, 0);
4549
        break;
4550
#endif
4551
    case TARGET_NR_getcwd:
4552 4553
        if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
            goto efault;
4554 4555
        ret = get_errno(sys_getcwd1(p, arg2));
        unlock_user(p, arg1, ret);
4556 4557
        break;
    case TARGET_NR_capget:
B
bellard 已提交
4558
        goto unimplemented;
4559
    case TARGET_NR_capset:
B
bellard 已提交
4560
        goto unimplemented;
4561
    case TARGET_NR_sigaltstack:
4562 4563
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
    defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
4564
        ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
4565 4566
        break;
#else
B
bellard 已提交
4567
        goto unimplemented;
4568
#endif
4569
    case TARGET_NR_sendfile:
B
bellard 已提交
4570
        goto unimplemented;
4571
#ifdef TARGET_NR_getpmsg
4572
    case TARGET_NR_getpmsg:
B
bellard 已提交
4573
        goto unimplemented;
4574 4575
#endif
#ifdef TARGET_NR_putpmsg
4576
    case TARGET_NR_putpmsg:
B
bellard 已提交
4577
        goto unimplemented;
4578
#endif
B
bellard 已提交
4579
#ifdef TARGET_NR_vfork
4580
    case TARGET_NR_vfork:
B
bellard 已提交
4581
        ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0));
4582
        break;
B
bellard 已提交
4583
#endif
4584
#ifdef TARGET_NR_ugetrlimit
4585
    case TARGET_NR_ugetrlimit:
B
bellard 已提交
4586 4587 4588 4589
    {
	struct rlimit rlim;
	ret = get_errno(getrlimit(arg1, &rlim));
	if (!is_error(ret)) {
4590
	    struct target_rlimit *target_rlim;
4591 4592
            if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
                goto efault;
B
bellard 已提交
4593 4594
	    target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
	    target_rlim->rlim_max = tswapl(rlim.rlim_max);
4595
            unlock_user_struct(target_rlim, arg2, 1);
B
bellard 已提交
4596 4597 4598
	}
	break;
    }
4599
#endif
B
bellard 已提交
4600
#ifdef TARGET_NR_truncate64
4601
    case TARGET_NR_truncate64:
4602 4603
        if (!(p = lock_user_string(arg1)))
            goto efault;
4604 4605
	ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
        unlock_user(p, arg1, 0);
B
bellard 已提交
4606
	break;
B
bellard 已提交
4607 4608
#endif
#ifdef TARGET_NR_ftruncate64
4609
    case TARGET_NR_ftruncate64:
P
pbrook 已提交
4610
	ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
B
bellard 已提交
4611
	break;
B
bellard 已提交
4612 4613
#endif
#ifdef TARGET_NR_stat64
4614
    case TARGET_NR_stat64:
4615 4616
        if (!(p = lock_user_string(arg1)))
            goto efault;
4617 4618
        ret = get_errno(stat(path(p), &st));
        unlock_user(p, arg1, 0);
B
bellard 已提交
4619
        goto do_stat64;
B
bellard 已提交
4620 4621
#endif
#ifdef TARGET_NR_lstat64
4622
    case TARGET_NR_lstat64:
4623 4624
        if (!(p = lock_user_string(arg1)))
            goto efault;
4625 4626
        ret = get_errno(lstat(path(p), &st));
        unlock_user(p, arg1, 0);
B
bellard 已提交
4627
        goto do_stat64;
B
bellard 已提交
4628 4629
#endif
#ifdef TARGET_NR_fstat64
4630
    case TARGET_NR_fstat64:
B
bellard 已提交
4631 4632 4633 4634
        {
            ret = get_errno(fstat(arg1, &st));
        do_stat64:
            if (!is_error(ret)) {
P
pbrook 已提交
4635 4636
#ifdef TARGET_ARM
                if (((CPUARMState *)cpu_env)->eabi) {
4637
                    struct target_eabi_stat64 *target_st;
4638 4639 4640

                    if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
                        goto efault;
P
pbrook 已提交
4641
                    memset(target_st, 0, sizeof(struct target_eabi_stat64));
4642 4643
                    __put_user(st.st_dev, &target_st->st_dev);
                    __put_user(st.st_ino, &target_st->st_ino);
P
pbrook 已提交
4644
#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658
                    __put_user(st.st_ino, &target_st->__st_ino);
#endif
                    __put_user(st.st_mode, &target_st->st_mode);
                    __put_user(st.st_nlink, &target_st->st_nlink);
                    __put_user(st.st_uid, &target_st->st_uid);
                    __put_user(st.st_gid, &target_st->st_gid);
                    __put_user(st.st_rdev, &target_st->st_rdev);
                    __put_user(st.st_size, &target_st->st_size);
                    __put_user(st.st_blksize, &target_st->st_blksize);
                    __put_user(st.st_blocks, &target_st->st_blocks);
                    __put_user(st.st_atime, &target_st->target_st_atime);
                    __put_user(st.st_mtime, &target_st->target_st_mtime);
                    __put_user(st.st_ctime, &target_st->target_st_ctime);
                    unlock_user_struct(target_st, arg2, 1);
P
pbrook 已提交
4659 4660 4661
                } else
#endif
                {
4662
                    struct target_stat64 *target_st;
4663 4664 4665

                    if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
                        goto efault;
P
pbrook 已提交
4666
                    memset(target_st, 0, sizeof(struct target_stat64));
4667 4668
                    __put_user(st.st_dev, &target_st->st_dev);
                    __put_user(st.st_ino, &target_st->st_ino);
4669
#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
4670
                    __put_user(st.st_ino, &target_st->__st_ino);
P
pbrook 已提交
4671
#endif
4672 4673 4674 4675 4676
                    __put_user(st.st_mode, &target_st->st_mode);
                    __put_user(st.st_nlink, &target_st->st_nlink);
                    __put_user(st.st_uid, &target_st->st_uid);
                    __put_user(st.st_gid, &target_st->st_gid);
                    __put_user(st.st_rdev, &target_st->st_rdev);
P
pbrook 已提交
4677
                    /* XXX: better use of kernel struct */
4678 4679 4680 4681 4682 4683 4684
                    __put_user(st.st_size, &target_st->st_size);
                    __put_user(st.st_blksize, &target_st->st_blksize);
                    __put_user(st.st_blocks, &target_st->st_blocks);
                    __put_user(st.st_atime, &target_st->target_st_atime);
                    __put_user(st.st_mtime, &target_st->target_st_mtime);
                    __put_user(st.st_ctime, &target_st->target_st_ctime);
                    unlock_user_struct(target_st, arg2, 1);
P
pbrook 已提交
4685
                }
B
bellard 已提交
4686 4687 4688
            }
        }
        break;
B
bellard 已提交
4689
#endif
4690 4691
#ifdef USE_UID16
    case TARGET_NR_lchown:
4692 4693
        if (!(p = lock_user_string(arg1)))
            goto efault;
4694 4695
        ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
        unlock_user(p, arg1, 0);
4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717
        break;
    case TARGET_NR_getuid:
        ret = get_errno(high2lowuid(getuid()));
        break;
    case TARGET_NR_getgid:
        ret = get_errno(high2lowgid(getgid()));
        break;
    case TARGET_NR_geteuid:
        ret = get_errno(high2lowuid(geteuid()));
        break;
    case TARGET_NR_getegid:
        ret = get_errno(high2lowgid(getegid()));
        break;
    case TARGET_NR_setreuid:
        ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
        break;
    case TARGET_NR_setregid:
        ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
        break;
    case TARGET_NR_getgroups:
        {
            int gidsetsize = arg1;
4718
            uint16_t *target_grouplist;
4719 4720 4721 4722 4723 4724
            gid_t *grouplist;
            int i;

            grouplist = alloca(gidsetsize * sizeof(gid_t));
            ret = get_errno(getgroups(gidsetsize, grouplist));
            if (!is_error(ret)) {
4725 4726 4727
                target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
                if (!target_grouplist)
                    goto efault;
4728 4729
                for(i = 0;i < gidsetsize; i++)
                    target_grouplist[i] = tswap16(grouplist[i]);
4730
                unlock_user(target_grouplist, arg2, gidsetsize * 2);
4731 4732 4733 4734 4735 4736
            }
        }
        break;
    case TARGET_NR_setgroups:
        {
            int gidsetsize = arg1;
4737
            uint16_t *target_grouplist;
4738 4739 4740 4741
            gid_t *grouplist;
            int i;

            grouplist = alloca(gidsetsize * sizeof(gid_t));
4742 4743 4744 4745 4746
            target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
            if (!target_grouplist) {
                ret = -TARGET_EFAULT;
                goto fail;
            }
4747 4748
            for(i = 0;i < gidsetsize; i++)
                grouplist[i] = tswap16(target_grouplist[i]);
4749
            unlock_user(target_grouplist, arg2, 0);
4750 4751 4752 4753 4754 4755
            ret = get_errno(setgroups(gidsetsize, grouplist));
        }
        break;
    case TARGET_NR_fchown:
        ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
        break;
4756 4757
#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
    case TARGET_NR_fchownat:
4758 4759 4760 4761
        if (!(p = lock_user_string(arg2))) 
            goto efault;
        ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
        unlock_user(p, arg2, 0);
4762 4763
        break;
#endif
4764 4765
#ifdef TARGET_NR_setresuid
    case TARGET_NR_setresuid:
4766 4767
        ret = get_errno(setresuid(low2highuid(arg1),
                                  low2highuid(arg2),
4768 4769 4770 4771 4772 4773
                                  low2highuid(arg3)));
        break;
#endif
#ifdef TARGET_NR_getresuid
    case TARGET_NR_getresuid:
        {
4774
            uid_t ruid, euid, suid;
4775 4776
            ret = get_errno(getresuid(&ruid, &euid, &suid));
            if (!is_error(ret)) {
4777 4778 4779
                tput16(arg1, tswap16(high2lowuid(ruid)));
                tput16(arg2, tswap16(high2lowuid(euid)));
                tput16(arg3, tswap16(high2lowuid(suid)));
4780 4781 4782 4783 4784 4785
            }
        }
        break;
#endif
#ifdef TARGET_NR_getresgid
    case TARGET_NR_setresgid:
4786 4787
        ret = get_errno(setresgid(low2highgid(arg1),
                                  low2highgid(arg2),
4788 4789 4790 4791 4792 4793
                                  low2highgid(arg3)));
        break;
#endif
#ifdef TARGET_NR_getresgid
    case TARGET_NR_getresgid:
        {
4794
            gid_t rgid, egid, sgid;
4795 4796
            ret = get_errno(getresgid(&rgid, &egid, &sgid));
            if (!is_error(ret)) {
4797 4798 4799
                tput16(arg1, tswap16(high2lowgid(rgid)));
                tput16(arg2, tswap16(high2lowgid(egid)));
                tput16(arg3, tswap16(high2lowgid(sgid)));
4800 4801 4802 4803 4804
            }
        }
        break;
#endif
    case TARGET_NR_chown:
4805 4806
        if (!(p = lock_user_string(arg1)))
            goto efault;
4807 4808
        ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
        unlock_user(p, arg1, 0);
4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823
        break;
    case TARGET_NR_setuid:
        ret = get_errno(setuid(low2highuid(arg1)));
        break;
    case TARGET_NR_setgid:
        ret = get_errno(setgid(low2highgid(arg1)));
        break;
    case TARGET_NR_setfsuid:
        ret = get_errno(setfsuid(arg1));
        break;
    case TARGET_NR_setfsgid:
        ret = get_errno(setfsgid(arg1));
        break;
#endif /* USE_UID16 */

B
bellard 已提交
4824
#ifdef TARGET_NR_lchown32
4825
    case TARGET_NR_lchown32:
4826 4827
        if (!(p = lock_user_string(arg1)))
            goto efault;
4828 4829
        ret = get_errno(lchown(p, arg2, arg3));
        unlock_user(p, arg1, 0);
B
bellard 已提交
4830
        break;
B
bellard 已提交
4831 4832
#endif
#ifdef TARGET_NR_getuid32
4833
    case TARGET_NR_getuid32:
B
bellard 已提交
4834 4835
        ret = get_errno(getuid());
        break;
B
bellard 已提交
4836 4837
#endif
#ifdef TARGET_NR_getgid32
4838
    case TARGET_NR_getgid32:
B
bellard 已提交
4839 4840
        ret = get_errno(getgid());
        break;
B
bellard 已提交
4841 4842
#endif
#ifdef TARGET_NR_geteuid32
4843
    case TARGET_NR_geteuid32:
B
bellard 已提交
4844 4845
        ret = get_errno(geteuid());
        break;
B
bellard 已提交
4846 4847
#endif
#ifdef TARGET_NR_getegid32
4848
    case TARGET_NR_getegid32:
B
bellard 已提交
4849 4850
        ret = get_errno(getegid());
        break;
B
bellard 已提交
4851 4852
#endif
#ifdef TARGET_NR_setreuid32
4853
    case TARGET_NR_setreuid32:
B
bellard 已提交
4854 4855
        ret = get_errno(setreuid(arg1, arg2));
        break;
B
bellard 已提交
4856 4857
#endif
#ifdef TARGET_NR_setregid32
4858
    case TARGET_NR_setregid32:
B
bellard 已提交
4859 4860
        ret = get_errno(setregid(arg1, arg2));
        break;
B
bellard 已提交
4861 4862
#endif
#ifdef TARGET_NR_getgroups32
4863
    case TARGET_NR_getgroups32:
B
bellard 已提交
4864 4865
        {
            int gidsetsize = arg1;
4866
            uint32_t *target_grouplist;
B
bellard 已提交
4867 4868 4869 4870 4871 4872
            gid_t *grouplist;
            int i;

            grouplist = alloca(gidsetsize * sizeof(gid_t));
            ret = get_errno(getgroups(gidsetsize, grouplist));
            if (!is_error(ret)) {
4873 4874 4875 4876 4877
                target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
                if (!target_grouplist) {
                    ret = -TARGET_EFAULT;
                    goto fail;
                }
B
bellard 已提交
4878
                for(i = 0;i < gidsetsize; i++)
4879 4880
                    target_grouplist[i] = tswap32(grouplist[i]);
                unlock_user(target_grouplist, arg2, gidsetsize * 4);
B
bellard 已提交
4881 4882 4883
            }
        }
        break;
B
bellard 已提交
4884 4885
#endif
#ifdef TARGET_NR_setgroups32
4886
    case TARGET_NR_setgroups32:
B
bellard 已提交
4887 4888
        {
            int gidsetsize = arg1;
4889
            uint32_t *target_grouplist;
B
bellard 已提交
4890 4891
            gid_t *grouplist;
            int i;
4892

B
bellard 已提交
4893
            grouplist = alloca(gidsetsize * sizeof(gid_t));
4894 4895 4896 4897 4898
            target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
            if (!target_grouplist) {
                ret = -TARGET_EFAULT;
                goto fail;
            }
B
bellard 已提交
4899
            for(i = 0;i < gidsetsize; i++)
4900 4901
                grouplist[i] = tswap32(target_grouplist[i]);
            unlock_user(target_grouplist, arg2, 0);
B
bellard 已提交
4902 4903 4904
            ret = get_errno(setgroups(gidsetsize, grouplist));
        }
        break;
B
bellard 已提交
4905 4906
#endif
#ifdef TARGET_NR_fchown32
4907
    case TARGET_NR_fchown32:
B
bellard 已提交
4908 4909
        ret = get_errno(fchown(arg1, arg2, arg3));
        break;
B
bellard 已提交
4910 4911
#endif
#ifdef TARGET_NR_setresuid32
4912
    case TARGET_NR_setresuid32:
B
bellard 已提交
4913 4914
        ret = get_errno(setresuid(arg1, arg2, arg3));
        break;
B
bellard 已提交
4915 4916
#endif
#ifdef TARGET_NR_getresuid32
4917
    case TARGET_NR_getresuid32:
B
bellard 已提交
4918
        {
4919
            uid_t ruid, euid, suid;
B
bellard 已提交
4920 4921
            ret = get_errno(getresuid(&ruid, &euid, &suid));
            if (!is_error(ret)) {
4922 4923 4924
                tput32(arg1, tswap32(ruid));
                tput32(arg2, tswap32(euid));
                tput32(arg3, tswap32(suid));
B
bellard 已提交
4925 4926 4927
            }
        }
        break;
B
bellard 已提交
4928 4929
#endif
#ifdef TARGET_NR_setresgid32
4930
    case TARGET_NR_setresgid32:
B
bellard 已提交
4931 4932
        ret = get_errno(setresgid(arg1, arg2, arg3));
        break;
B
bellard 已提交
4933 4934
#endif
#ifdef TARGET_NR_getresgid32
4935
    case TARGET_NR_getresgid32:
B
bellard 已提交
4936
        {
4937
            gid_t rgid, egid, sgid;
B
bellard 已提交
4938 4939
            ret = get_errno(getresgid(&rgid, &egid, &sgid));
            if (!is_error(ret)) {
4940 4941 4942
                tput32(arg1, tswap32(rgid));
                tput32(arg2, tswap32(egid));
                tput32(arg3, tswap32(sgid));
B
bellard 已提交
4943 4944 4945
            }
        }
        break;
B
bellard 已提交
4946 4947
#endif
#ifdef TARGET_NR_chown32
4948
    case TARGET_NR_chown32:
4949 4950
        if (!(p = lock_user_string(arg1)))
            goto efault;
4951 4952
        ret = get_errno(chown(p, arg2, arg3));
        unlock_user(p, arg1, 0);
B
bellard 已提交
4953
        break;
B
bellard 已提交
4954 4955
#endif
#ifdef TARGET_NR_setuid32
4956
    case TARGET_NR_setuid32:
B
bellard 已提交
4957 4958
        ret = get_errno(setuid(arg1));
        break;
B
bellard 已提交
4959 4960
#endif
#ifdef TARGET_NR_setgid32
4961
    case TARGET_NR_setgid32:
B
bellard 已提交
4962 4963
        ret = get_errno(setgid(arg1));
        break;
B
bellard 已提交
4964 4965
#endif
#ifdef TARGET_NR_setfsuid32
4966
    case TARGET_NR_setfsuid32:
B
bellard 已提交
4967 4968
        ret = get_errno(setfsuid(arg1));
        break;
B
bellard 已提交
4969 4970
#endif
#ifdef TARGET_NR_setfsgid32
4971
    case TARGET_NR_setfsgid32:
B
bellard 已提交
4972 4973
        ret = get_errno(setfsgid(arg1));
        break;
B
bellard 已提交
4974
#endif
4975

4976
    case TARGET_NR_pivot_root:
B
bellard 已提交
4977
        goto unimplemented;
B
bellard 已提交
4978
#ifdef TARGET_NR_mincore
4979
    case TARGET_NR_mincore:
B
bellard 已提交
4980
        goto unimplemented;
B
bellard 已提交
4981 4982
#endif
#ifdef TARGET_NR_madvise
4983
    case TARGET_NR_madvise:
4984 4985 4986 4987 4988 4989
        /* A straight passthrough may not be safe because qemu sometimes
           turns private flie-backed mappings into anonymous mappings.
           This will break MADV_DONTNEED.
           This is a hint, so ignoring and returning success is ok.  */
        ret = get_errno(0);
        break;
B
bellard 已提交
4990
#endif
4991
#if TARGET_ABI_BITS == 32
4992
    case TARGET_NR_fcntl64:
B
bellard 已提交
4993
    {
T
ths 已提交
4994
	int cmd;
B
bellard 已提交
4995
	struct flock64 fl;
4996
	struct target_flock64 *target_fl;
P
pbrook 已提交
4997
#ifdef TARGET_ARM
4998
	struct target_eabi_flock64 *target_efl;
P
pbrook 已提交
4999
#endif
B
bellard 已提交
5000

T
ths 已提交
5001 5002 5003
        switch(arg2){
        case TARGET_F_GETLK64:
            cmd = F_GETLK64;
5004
            break;
T
ths 已提交
5005 5006
        case TARGET_F_SETLK64:
            cmd = F_SETLK64;
5007
            break;
T
ths 已提交
5008 5009
        case TARGET_F_SETLKW64:
            cmd = F_SETLK64;
5010
            break;
T
ths 已提交
5011 5012
        default:
            cmd = arg2;
5013
            break;
T
ths 已提交
5014 5015
        }

B
bellard 已提交
5016
        switch(arg2) {
T
ths 已提交
5017
        case TARGET_F_GETLK64:
T
ths 已提交
5018 5019
#ifdef TARGET_ARM
            if (((CPUARMState *)cpu_env)->eabi) {
B
bellard 已提交
5020 5021
                if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1)) 
                    goto efault;
T
ths 已提交
5022 5023 5024 5025 5026 5027 5028 5029 5030
                fl.l_type = tswap16(target_efl->l_type);
                fl.l_whence = tswap16(target_efl->l_whence);
                fl.l_start = tswap64(target_efl->l_start);
                fl.l_len = tswap64(target_efl->l_len);
                fl.l_pid = tswapl(target_efl->l_pid);
                unlock_user_struct(target_efl, arg3, 0);
            } else
#endif
            {
B
bellard 已提交
5031 5032
                if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1)) 
                    goto efault;
T
ths 已提交
5033 5034 5035 5036 5037 5038 5039
                fl.l_type = tswap16(target_fl->l_type);
                fl.l_whence = tswap16(target_fl->l_whence);
                fl.l_start = tswap64(target_fl->l_start);
                fl.l_len = tswap64(target_fl->l_len);
                fl.l_pid = tswapl(target_fl->l_pid);
                unlock_user_struct(target_fl, arg3, 0);
            }
T
ths 已提交
5040
            ret = get_errno(fcntl(arg1, cmd, &fl));
B
bellard 已提交
5041
	    if (ret == 0) {
P
pbrook 已提交
5042 5043
#ifdef TARGET_ARM
                if (((CPUARMState *)cpu_env)->eabi) {
B
bellard 已提交
5044 5045
                    if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0)) 
                        goto efault;
P
pbrook 已提交
5046 5047 5048 5049 5050
                    target_efl->l_type = tswap16(fl.l_type);
                    target_efl->l_whence = tswap16(fl.l_whence);
                    target_efl->l_start = tswap64(fl.l_start);
                    target_efl->l_len = tswap64(fl.l_len);
                    target_efl->l_pid = tswapl(fl.l_pid);
5051
                    unlock_user_struct(target_efl, arg3, 1);
P
pbrook 已提交
5052 5053 5054
                } else
#endif
                {
B
bellard 已提交
5055 5056
                    if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0)) 
                        goto efault;
P
pbrook 已提交
5057 5058 5059 5060 5061
                    target_fl->l_type = tswap16(fl.l_type);
                    target_fl->l_whence = tswap16(fl.l_whence);
                    target_fl->l_start = tswap64(fl.l_start);
                    target_fl->l_len = tswap64(fl.l_len);
                    target_fl->l_pid = tswapl(fl.l_pid);
5062
                    unlock_user_struct(target_fl, arg3, 1);
P
pbrook 已提交
5063
                }
B
bellard 已提交
5064 5065 5066
	    }
	    break;

T
ths 已提交
5067 5068
        case TARGET_F_SETLK64:
        case TARGET_F_SETLKW64:
P
pbrook 已提交
5069 5070
#ifdef TARGET_ARM
            if (((CPUARMState *)cpu_env)->eabi) {
B
bellard 已提交
5071 5072
                if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1)) 
                    goto efault;
P
pbrook 已提交
5073 5074 5075 5076 5077
                fl.l_type = tswap16(target_efl->l_type);
                fl.l_whence = tswap16(target_efl->l_whence);
                fl.l_start = tswap64(target_efl->l_start);
                fl.l_len = tswap64(target_efl->l_len);
                fl.l_pid = tswapl(target_efl->l_pid);
5078
                unlock_user_struct(target_efl, arg3, 0);
P
pbrook 已提交
5079 5080 5081
            } else
#endif
            {
B
bellard 已提交
5082 5083
                if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1)) 
                    goto efault;
P
pbrook 已提交
5084 5085 5086 5087 5088
                fl.l_type = tswap16(target_fl->l_type);
                fl.l_whence = tswap16(target_fl->l_whence);
                fl.l_start = tswap64(target_fl->l_start);
                fl.l_len = tswap64(target_fl->l_len);
                fl.l_pid = tswapl(target_fl->l_pid);
5089
                unlock_user_struct(target_fl, arg3, 0);
P
pbrook 已提交
5090
            }
T
ths 已提交
5091
            ret = get_errno(fcntl(arg1, cmd, &fl));
B
bellard 已提交
5092
	    break;
B
bellard 已提交
5093
        default:
B
bellard 已提交
5094
            ret = do_fcntl(arg1, cmd, arg3);
B
bellard 已提交
5095 5096
            break;
        }
B
bellard 已提交
5097 5098
	break;
    }
B
bellard 已提交
5099
#endif
5100 5101 5102 5103 5104 5105
#ifdef TARGET_NR_cacheflush
    case TARGET_NR_cacheflush:
        /* self-modifying code is handled automatically, so nothing needed */
        ret = 0;
        break;
#endif
5106
#ifdef TARGET_NR_security
5107 5108
    case TARGET_NR_security:
        goto unimplemented;
B
bellard 已提交
5109 5110 5111 5112 5113
#endif
#ifdef TARGET_NR_getpagesize
    case TARGET_NR_getpagesize:
        ret = TARGET_PAGE_SIZE;
        break;
5114
#endif
5115 5116 5117
    case TARGET_NR_gettid:
        ret = get_errno(gettid());
        break;
5118
#ifdef TARGET_NR_readahead
5119
    case TARGET_NR_readahead:
B
bellard 已提交
5120
        goto unimplemented;
5121
#endif
5122
#ifdef TARGET_NR_setxattr
5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134
    case TARGET_NR_setxattr:
    case TARGET_NR_lsetxattr:
    case TARGET_NR_fsetxattr:
    case TARGET_NR_getxattr:
    case TARGET_NR_lgetxattr:
    case TARGET_NR_fgetxattr:
    case TARGET_NR_listxattr:
    case TARGET_NR_llistxattr:
    case TARGET_NR_flistxattr:
    case TARGET_NR_removexattr:
    case TARGET_NR_lremovexattr:
    case TARGET_NR_fremovexattr:
B
bellard 已提交
5135
        goto unimplemented_nowarn;
5136 5137
#endif
#ifdef TARGET_NR_set_thread_area
B
bellard 已提交
5138
    case TARGET_NR_set_thread_area:
5139 5140 5141 5142 5143 5144 5145 5146 5147
#ifdef TARGET_MIPS
      ((CPUMIPSState *) cpu_env)->tls_value = arg1;
      ret = 0;
      break;
#else
      goto unimplemented_nowarn;
#endif
#endif
#ifdef TARGET_NR_get_thread_area
B
bellard 已提交
5148 5149
    case TARGET_NR_get_thread_area:
        goto unimplemented_nowarn;
B
bellard 已提交
5150 5151 5152 5153
#endif
#ifdef TARGET_NR_getdomainname
    case TARGET_NR_getdomainname:
        goto unimplemented_nowarn;
5154
#endif
5155

5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178
#ifdef TARGET_NR_clock_gettime
    case TARGET_NR_clock_gettime:
    {
        struct timespec ts;
        ret = get_errno(clock_gettime(arg1, &ts));
        if (!is_error(ret)) {
            host_to_target_timespec(arg2, &ts);
        }
        break;
    }
#endif
#ifdef TARGET_NR_clock_getres
    case TARGET_NR_clock_getres:
    {
        struct timespec ts;
        ret = get_errno(clock_getres(arg1, &ts));
        if (!is_error(ret)) {
            host_to_target_timespec(arg2, &ts);
        }
        break;
    }
#endif

5179 5180
#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
    case TARGET_NR_set_tid_address:
5181 5182
        ret = get_errno(set_tid_address((int *)g2h(arg1)));
        break;
5183 5184
#endif

T
ths 已提交
5185
#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
T
ths 已提交
5186 5187 5188 5189 5190
    case TARGET_NR_tkill:
        ret = get_errno(sys_tkill((int)arg1, (int)arg2));
        break;
#endif

T
ths 已提交
5191
#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
T
ths 已提交
5192 5193 5194 5195 5196
    case TARGET_NR_tgkill:
	ret = get_errno(sys_tgkill((int)arg1, (int)arg2, (int)arg3));
	break;
#endif

5197 5198 5199 5200 5201
#ifdef TARGET_NR_set_robust_list
    case TARGET_NR_set_robust_list:
	goto unimplemented_nowarn;
#endif

5202 5203 5204 5205 5206 5207 5208 5209 5210
#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
    case TARGET_NR_utimensat:
        {
            struct timespec ts[2];
            target_to_host_timespec(ts, arg3);
            target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
            if (!arg2)
                ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4));
            else {
5211
                if (!(p = lock_user_string(arg2))) {
5212
                    ret = -TARGET_EFAULT;
5213 5214 5215 5216
                    goto fail;
                }
                ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
                unlock_user(p, arg2, 0);
5217 5218 5219 5220 5221
            }
        }
	break;
#endif

5222 5223
    default:
    unimplemented:
B
bellard 已提交
5224
        gemu_log("qemu: Unsupported syscall: %d\n", num);
5225
#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname) || defined(TARGET_NR_set_robust_list)
B
bellard 已提交
5226
    unimplemented_nowarn:
B
bellard 已提交
5227
#endif
5228
        ret = -TARGET_ENOSYS;
5229 5230
        break;
    }
5231
fail:
B
bellard 已提交
5232 5233 5234
#ifdef DEBUG
    gemu_log(" = %ld\n", ret);
#endif
5235 5236
    if(do_strace)
        print_syscall_ret(num, ret);
5237
    return ret;
5238 5239 5240
efault:
    ret = -TARGET_EFAULT;
    goto fail;
5241
}