syscall.c 167.9 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
    int seg_32bit, contents, read_exec_only, limit_in_pages;
B
bellard 已提交
2288
    int seg_not_present, useable, lm;
B
bellard 已提交
2289 2290 2291
    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
    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;
B
bellard 已提交
2309 2310 2311 2312 2313
#ifdef TARGET_ABI32
    lm = 0;
#else
    lm = (ldt_info.flags >> 7) & 1;
#endif
B
bellard 已提交
2314 2315
    if (contents == 3) {
        if (oldmode)
2316
            return -TARGET_EINVAL;
B
bellard 已提交
2317
        if (seg_not_present == 0)
2318
            return -TARGET_EINVAL;
B
bellard 已提交
2319 2320 2321 2322 2323
    }
    /* allocate the LDT */
    if (!ldt_table) {
        ldt_table = malloc(TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
        if (!ldt_table)
2324
            return -TARGET_ENOMEM;
B
bellard 已提交
2325
        memset(ldt_table, 0, TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
B
bellard 已提交
2326
        env->ldt.base = h2g((unsigned long)ldt_table);
B
bellard 已提交
2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344
        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;
        }
    }
2345

B
bellard 已提交
2346 2347 2348 2349 2350 2351 2352 2353 2354 2355
    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) |
B
bellard 已提交
2356
        (lm << 21) |
B
bellard 已提交
2357 2358 2359
        0x7000;
    if (!oldmode)
        entry_2 |= (useable << 20);
B
bellard 已提交
2360

B
bellard 已提交
2361 2362 2363 2364 2365 2366 2367 2368 2369
    /* 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 */
2370 2371
abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr, 
                       unsigned long bytecount)
B
bellard 已提交
2372
{
2373
    abi_long ret;
2374

B
bellard 已提交
2375 2376 2377 2378 2379 2380 2381 2382 2383 2384
    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;
2385 2386 2387
    default:
        ret = -TARGET_ENOSYS;
        break;
B
bellard 已提交
2388 2389 2390
    }
    return ret;
}
B
bellard 已提交
2391

B
bellard 已提交
2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523
abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
{
    uint64_t *gdt_table = g2h(env->gdt.base);
    struct target_modify_ldt_ldt_s ldt_info;
    struct target_modify_ldt_ldt_s *target_ldt_info;
    int seg_32bit, contents, read_exec_only, limit_in_pages;
    int seg_not_present, useable, lm;
    uint32_t *lp, entry_1, entry_2;
    int i;

    lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
    if (!target_ldt_info)
        return -TARGET_EFAULT;
    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);
    if (ldt_info.entry_number == -1) {
        for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
            if (gdt_table[i] == 0) {
                ldt_info.entry_number = i;
                target_ldt_info->entry_number = tswap32(i);
                break;
            }
        }
    }
    unlock_user_struct(target_ldt_info, ptr, 1);

    if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN || 
        ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
           return -TARGET_EINVAL;
    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;
#ifdef TARGET_ABI32
    lm = 0;
#else
    lm = (ldt_info.flags >> 7) & 1;
#endif

    if (contents == 3) {
        if (seg_not_present == 0)
            return -TARGET_EINVAL;
    }

    /* 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 ((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;
        }
    }

    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) |
        (useable << 20) |
        (lm << 21) |
        0x7000;

    /* Install the new entry ...  */
install:
    lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
    lp[0] = tswap32(entry_1);
    lp[1] = tswap32(entry_2);
    return 0;
}

abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
{
    struct target_modify_ldt_ldt_s *target_ldt_info;
    uint64_t *gdt_table = g2h(env->gdt.base);
    uint32_t base_addr, limit, flags;
    int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
    int seg_not_present, useable, lm;
    uint32_t *lp, entry_1, entry_2;

    lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
    if (!target_ldt_info)
        return -TARGET_EFAULT;
    idx = tswap32(target_ldt_info->entry_number);
    if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
        idx > TARGET_GDT_ENTRY_TLS_MAX) {
        unlock_user_struct(target_ldt_info, ptr, 1);
        return -TARGET_EINVAL;
    }
    lp = (uint32_t *)(gdt_table + idx);
    entry_1 = tswap32(lp[0]);
    entry_2 = tswap32(lp[1]);
    
    read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
    contents = (entry_2 >> 10) & 3;
    seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
    seg_32bit = (entry_2 >> 22) & 1;
    limit_in_pages = (entry_2 >> 23) & 1;
    useable = (entry_2 >> 20) & 1;
#ifdef TARGET_ABI32
    lm = 0;
#else
    lm = (entry_2 >> 21) & 1;
#endif
    flags = (seg_32bit << 0) | (contents << 1) |
        (read_exec_only << 3) | (limit_in_pages << 4) |
        (seg_not_present << 5) | (useable << 6) | (lm << 7);
    limit = (entry_1 & 0xffff) | (entry_2  & 0xf0000);
    base_addr = (entry_1 >> 16) | 
        (entry_2 & 0xff000000) | 
        ((entry_2 & 0xff) << 16);
    target_ldt_info->base_addr = tswapl(base_addr);
    target_ldt_info->limit = tswap32(limit);
    target_ldt_info->flags = tswap32(flags);
    unlock_user_struct(target_ldt_info, ptr, 1);
    return 0;
}

2524 2525
#endif /* defined(TARGET_I386) */

B
bellard 已提交
2526 2527 2528 2529 2530 2531
/* 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)
{
2532
    CPUState *env = arg;
B
bellard 已提交
2533 2534 2535 2536 2537
    cpu_loop(env);
    /* never exits */
    return 0;
}

2538 2539
/* do_fork() Must return host values and target errnos (unlike most
   do_*() functions). */
2540
int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp)
B
bellard 已提交
2541 2542
{
    int ret;
B
bellard 已提交
2543
    TaskState *ts;
B
bellard 已提交
2544
    uint8_t *new_stack;
2545
    CPUState *new_env;
2546

B
bellard 已提交
2547
    if (flags & CLONE_VM) {
B
bellard 已提交
2548 2549 2550 2551 2552 2553 2554
        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 已提交
2555
        /* we create a new CPU instance. */
2556
        new_env = cpu_copy(env);
2557 2558 2559
#if defined(TARGET_I386)
        if (!newsp)
            newsp = env->regs[R_ESP];
B
bellard 已提交
2560 2561
        new_env->regs[R_ESP] = newsp;
        new_env->regs[R_EAX] = 0;
2562 2563 2564 2565 2566
#elif defined(TARGET_ARM)
        if (!newsp)
            newsp = env->regs[13];
        new_env->regs[13] = newsp;
        new_env->regs[0] = 0;
2567
#elif defined(TARGET_SPARC)
B
bellard 已提交
2568 2569 2570 2571 2572
        if (!newsp)
            newsp = env->regwptr[22];
        new_env->regwptr[22] = newsp;
        new_env->regwptr[0] = 0;
	/* XXXXX */
2573
        printf ("HELPME: %s:%d\n", __FILE__, __LINE__);
P
pbrook 已提交
2574 2575 2576 2577 2578 2579
#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 已提交
2580
#elif defined(TARGET_MIPS)
T
ths 已提交
2581
        if (!newsp)
2582 2583
            newsp = env->gpr[29][env->current_tc];
        new_env->gpr[29][env->current_tc] = newsp;
2584 2585 2586 2587
#elif defined(TARGET_PPC)
        if (!newsp)
            newsp = env->gpr[1];
        new_env->gpr[1] = newsp;
2588
        {
2589 2590 2591 2592
            int i;
            for (i = 7; i < 32; i++)
                new_env->gpr[i] = 0;
        }
B
bellard 已提交
2593 2594 2595 2596 2597
#elif defined(TARGET_SH4)
	if (!newsp)
	  newsp = env->gregs[15];
	new_env->gregs[15] = newsp;
	/* XXXXX */
2598 2599 2600 2601 2602 2603 2604 2605 2606 2607
#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;
        }
2608 2609 2610 2611
#elif defined(TARGET_CRIS)
	if (!newsp)
	  newsp = env->regs[14];
	new_env->regs[14] = newsp;
2612 2613 2614
#else
#error unsupported target CPU
#endif
B
bellard 已提交
2615
        new_env->opaque = ts;
2616
#ifdef __ia64__
B
bellard 已提交
2617
        ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
2618 2619 2620
#else
	ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
#endif
B
bellard 已提交
2621 2622 2623 2624 2625 2626 2627 2628 2629
    } else {
        /* if no CLONE_VM, we consider it is a fork */
        if ((flags & ~CSIGNAL) != 0)
            return -EINVAL;
        ret = fork();
    }
    return ret;
}

2630
static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
B
bellard 已提交
2631 2632
{
    struct flock fl;
2633
    struct target_flock *target_fl;
2634 2635
    struct flock64 fl64;
    struct target_flock64 *target_fl64;
2636
    abi_long ret;
2637

B
bellard 已提交
2638 2639
    switch(cmd) {
    case TARGET_F_GETLK:
2640 2641
        if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
            return -TARGET_EFAULT;
T
ths 已提交
2642 2643 2644 2645 2646 2647
        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 已提交
2648
        ret = get_errno(fcntl(fd, cmd, &fl));
B
bellard 已提交
2649
        if (ret == 0) {
2650 2651
            if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
                return -TARGET_EFAULT;
B
bellard 已提交
2652 2653 2654 2655 2656
            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);
2657
            unlock_user_struct(target_fl, arg, 1);
B
bellard 已提交
2658 2659
        }
        break;
2660

B
bellard 已提交
2661 2662
    case TARGET_F_SETLK:
    case TARGET_F_SETLKW:
2663 2664
        if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
            return -TARGET_EFAULT;
B
bellard 已提交
2665 2666 2667 2668 2669
        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);
2670
        unlock_user_struct(target_fl, arg, 0);
B
bellard 已提交
2671
        ret = get_errno(fcntl(fd, cmd, &fl));
B
bellard 已提交
2672
        break;
2673

B
bellard 已提交
2674
    case TARGET_F_GETLK64:
2675 2676
        if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
            return -TARGET_EFAULT;
T
ths 已提交
2677 2678 2679 2680 2681 2682
        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 已提交
2683
        ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
2684
        if (ret == 0) {
2685 2686
            if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
                return -TARGET_EFAULT;
2687 2688 2689 2690 2691 2692 2693
            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 已提交
2694
        break;
B
bellard 已提交
2695 2696
    case TARGET_F_SETLK64:
    case TARGET_F_SETLKW64:
2697 2698
        if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
            return -TARGET_EFAULT;
2699 2700 2701 2702 2703 2704
        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 已提交
2705
        ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
B
bellard 已提交
2706 2707
        break;

B
bellard 已提交
2708
    case F_GETFL:
B
bellard 已提交
2709 2710 2711 2712
        ret = get_errno(fcntl(fd, cmd, arg));
        if (ret >= 0) {
            ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
        }
B
bellard 已提交
2713 2714 2715
        break;

    case F_SETFL:
B
bellard 已提交
2716
        ret = get_errno(fcntl(fd, cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
B
bellard 已提交
2717 2718
        break;

B
bellard 已提交
2719
    default:
B
bellard 已提交
2720
        ret = get_errno(fcntl(fd, cmd, arg));
B
bellard 已提交
2721 2722 2723 2724 2725
        break;
    }
    return ret;
}

2726
#ifdef USE_UID16
B
bellard 已提交
2727

2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760
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 已提交
2761

2762 2763
void syscall_init(void)
{
2764 2765 2766
    IOCTLEntry *ie;
    const argtype *arg_type;
    int size;
2767
    int i;
2768

2769 2770
#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);
2771 2772 2773
#include "syscall_types.h"
#undef STRUCT
#undef STRUCT_SPECIAL
2774 2775 2776 2777 2778 2779 2780 2781 2782

    /* 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) {
2783
                fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
2784 2785 2786 2787 2788
                        ie->target_cmd);
                exit(1);
            }
            arg_type++;
            size = thunk_type_size(arg_type, 0);
2789
            ie->target_cmd = (ie->target_cmd &
2790 2791 2792
                              ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
                (size << TARGET_IOC_SIZESHIFT);
        }
2793 2794 2795 2796 2797 2798

        /* 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;

2799 2800 2801
        /* automatic consistency check if same arch */
#if defined(__i386__) && defined(TARGET_I386)
        if (ie->target_cmd != ie->host_cmd) {
2802
            fprintf(stderr, "ERROR: ioctl: target=0x%x host=0x%x\n",
2803 2804 2805 2806 2807
                    ie->target_cmd, ie->host_cmd);
        }
#endif
        ie++;
    }
2808
}
B
bellard 已提交
2809

2810
#if TARGET_ABI_BITS == 32
P
pbrook 已提交
2811 2812 2813 2814 2815 2816 2817 2818
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
}
2819
#else /* TARGET_ABI_BITS == 32 */
2820 2821 2822 2823
static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
{
    return word0;
}
2824
#endif /* TARGET_ABI_BITS != 32 */
P
pbrook 已提交
2825 2826

#ifdef TARGET_NR_truncate64
2827 2828 2829 2830
static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
                                         abi_long arg2,
                                         abi_long arg3,
                                         abi_long arg4)
P
pbrook 已提交
2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843
{
#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
2844 2845 2846 2847
static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
                                          abi_long arg2,
                                          abi_long arg3,
                                          abi_long arg4)
P
pbrook 已提交
2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859
{
#ifdef TARGET_ARM
    if (((CPUARMState *)cpu_env)->eabi)
      {
        arg2 = arg3;
        arg3 = arg4;
      }
#endif
    return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
}
#endif

2860 2861
static inline abi_long target_to_host_timespec(struct timespec *host_ts,
                                               abi_ulong target_addr)
2862 2863 2864
{
    struct target_timespec *target_ts;

2865 2866
    if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
        return -TARGET_EFAULT;
2867 2868 2869 2870 2871
    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);
}

2872 2873
static inline abi_long host_to_target_timespec(abi_ulong target_addr,
                                               struct timespec *host_ts)
2874 2875 2876
{
    struct target_timespec *target_ts;

2877 2878
    if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
        return -TARGET_EFAULT;
2879 2880 2881 2882 2883
    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);
}

2884 2885 2886
/* 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>. */
2887 2888 2889
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)
2890
{
2891
    abi_long ret;
2892
    struct stat st;
B
bellard 已提交
2893
    struct statfs stfs;
2894
    void *p;
2895

B
bellard 已提交
2896
#ifdef DEBUG
B
bellard 已提交
2897
    gemu_log("syscall %d", num);
B
bellard 已提交
2898
#endif
2899 2900 2901
    if(do_strace)
        print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);

2902 2903
    switch(num) {
    case TARGET_NR_exit:
B
bellard 已提交
2904 2905 2906
#ifdef HAVE_GPROF
        _mcleanup();
#endif
2907
        gdb_exit(cpu_env, arg1);
B
bellard 已提交
2908
        /* XXX: should free thread stack and CPU env */
2909 2910 2911 2912
        _exit(arg1);
        ret = 0; /* avoid warning */
        break;
    case TARGET_NR_read:
2913 2914
        if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
            goto efault;
2915 2916
        ret = get_errno(read(arg1, p, arg3));
        unlock_user(p, arg2, ret);
2917 2918
        break;
    case TARGET_NR_write:
2919 2920
        if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
            goto efault;
2921 2922
        ret = get_errno(write(arg1, p, arg3));
        unlock_user(p, arg2, 0);
2923 2924
        break;
    case TARGET_NR_open:
2925 2926 2927 2928
        if (!(p = lock_user_string(arg1))) {
            return -TARGET_EFAULT;
            goto fail;
        }
2929
        ret = get_errno(open(path(p),
B
bellard 已提交
2930 2931
                             target_to_host_bitmask(arg2, fcntl_flags_tbl),
                             arg3));
2932
        unlock_user(p, arg1, 0);
2933
        break;
2934 2935
#if defined(TARGET_NR_openat) && defined(__NR_openat)
    case TARGET_NR_openat:
2936 2937 2938 2939 2940 2941 2942
        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);
2943 2944
        break;
#endif
2945 2946 2947 2948
    case TARGET_NR_close:
        ret = get_errno(close(arg1));
        break;
    case TARGET_NR_brk:
2949
        ret = do_brk(arg1);
2950 2951
        break;
    case TARGET_NR_fork:
B
bellard 已提交
2952
        ret = get_errno(do_fork(cpu_env, SIGCHLD, 0));
2953
        break;
2954
#ifdef TARGET_NR_waitpid
2955 2956
    case TARGET_NR_waitpid:
        {
2957 2958 2959 2960
            int status;
            ret = get_errno(waitpid(arg1, &status, arg3));
            if (!is_error(ret) && arg2)
                tput32(arg2, status);
2961 2962
        }
        break;
2963
#endif
2964
#ifdef TARGET_NR_creat /* not on alpha */
2965
    case TARGET_NR_creat:
2966 2967
        if (!(p = lock_user_string(arg1)))
            goto efault;
2968 2969
        ret = get_errno(creat(p, arg2));
        unlock_user(p, arg1, 0);
2970
        break;
2971
#endif
2972
    case TARGET_NR_link:
2973 2974 2975 2976
        {
            void * p2;
            p = lock_user_string(arg1);
            p2 = lock_user_string(arg2);
2977 2978 2979 2980
            if (!p || !p2)
                ret = -TARGET_EFAULT;
            else
                ret = get_errno(link(p, p2));
2981 2982 2983
            unlock_user(p2, arg2, 0);
            unlock_user(p, arg1, 0);
        }
2984
        break;
2985 2986 2987 2988
#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
    case TARGET_NR_linkat:
        {
            void * p2 = NULL;
2989 2990
            if (!arg2 || !arg4)
                goto efault;
2991 2992
            p  = lock_user_string(arg2);
            p2 = lock_user_string(arg4);
2993
            if (!p || !p2)
2994
                ret = -TARGET_EFAULT;
2995 2996
            else
                ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
2997 2998
            unlock_user(p, arg2, 0);
            unlock_user(p2, arg4, 0);
2999 3000 3001
        }
        break;
#endif
3002
    case TARGET_NR_unlink:
3003 3004
        if (!(p = lock_user_string(arg1)))
            goto efault;
3005 3006
        ret = get_errno(unlink(p));
        unlock_user(p, arg1, 0);
3007
        break;
3008 3009
#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
    case TARGET_NR_unlinkat:
3010 3011 3012 3013
        if (!(p = lock_user_string(arg2)))
            goto efault;
        ret = get_errno(sys_unlinkat(arg1, p, arg3));
        unlock_user(p, arg2, 0);
3014
#endif
3015
    case TARGET_NR_execve:
B
bellard 已提交
3016 3017
        {
            char **argp, **envp;
B
bellard 已提交
3018
            int argc, envc;
3019 3020 3021 3022
            abi_ulong gp;
            abi_ulong guest_argp;
            abi_ulong guest_envp;
            abi_ulong addr;
B
bellard 已提交
3023 3024
            char **q;

B
bellard 已提交
3025
            argc = 0;
3026 3027
            guest_argp = arg2;
            for (gp = guest_argp; tgetl(gp); gp++)
B
bellard 已提交
3028
                argc++;
B
bellard 已提交
3029
            envc = 0;
3030 3031
            guest_envp = arg3;
            for (gp = guest_envp; tgetl(gp); gp++)
B
bellard 已提交
3032 3033
                envc++;

B
bellard 已提交
3034 3035
            argp = alloca((argc + 1) * sizeof(void *));
            envp = alloca((envc + 1) * sizeof(void *));
B
bellard 已提交
3036

3037
            for (gp = guest_argp, q = argp; ;
3038
                  gp += sizeof(abi_ulong), q++) {
3039 3040 3041
                addr = tgetl(gp);
                if (!addr)
                    break;
3042 3043 3044 3045
                if (!(*q = lock_user_string(addr))) {
                    ret = -TARGET_EFAULT;
                    goto execve_fail;
                }
3046
            }
B
bellard 已提交
3047 3048
            *q = NULL;

3049
            for (gp = guest_envp, q = envp; ;
3050
                  gp += sizeof(abi_ulong), q++) {
3051 3052 3053
                addr = tgetl(gp);
                if (!addr)
                    break;
3054 3055 3056 3057
                if (!(*q = lock_user_string(addr))) {
                    ret = -TARGET_EFAULT;
                    goto execve_fail;
                }
3058
            }
B
bellard 已提交
3059
            *q = NULL;
B
bellard 已提交
3060

3061 3062 3063 3064
            if (!(p = lock_user_string(arg1))) {
                ret = -TARGET_EFAULT;
                goto execve_fail;
            }
3065 3066 3067
            ret = get_errno(execve(p, argp, envp));
            unlock_user(p, arg1, 0);

3068
        execve_fail:
3069
            for (gp = guest_argp, q = argp; *q;
3070
                  gp += sizeof(abi_ulong), q++) {
3071 3072 3073 3074
                addr = tgetl(gp);
                unlock_user(*q, addr, 0);
            }
            for (gp = guest_envp, q = envp; *q;
3075
                  gp += sizeof(abi_ulong), q++) {
3076 3077 3078
                addr = tgetl(gp);
                unlock_user(*q, addr, 0);
            }
B
bellard 已提交
3079
        }
3080 3081
        break;
    case TARGET_NR_chdir:
3082 3083
        if (!(p = lock_user_string(arg1)))
            goto efault;
3084 3085
        ret = get_errno(chdir(p));
        unlock_user(p, arg1, 0);
3086
        break;
B
bellard 已提交
3087
#ifdef TARGET_NR_time
3088 3089
    case TARGET_NR_time:
        {
3090 3091 3092 3093
            time_t host_time;
            ret = get_errno(time(&host_time));
            if (!is_error(ret) && arg1)
                tputl(arg1, host_time);
3094 3095
        }
        break;
B
bellard 已提交
3096
#endif
3097
    case TARGET_NR_mknod:
3098 3099
        if (!(p = lock_user_string(arg1)))
            goto efault;
3100 3101
        ret = get_errno(mknod(p, arg2, arg3));
        unlock_user(p, arg1, 0);
3102
        break;
3103 3104
#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
    case TARGET_NR_mknodat:
3105 3106 3107 3108
        if (!(p = lock_user_string(arg2)))
            goto efault;
        ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
        unlock_user(p, arg2, 0);
3109 3110
        break;
#endif
3111
    case TARGET_NR_chmod:
3112 3113
        if (!(p = lock_user_string(arg1)))
            goto efault;
3114 3115
        ret = get_errno(chmod(p, arg2));
        unlock_user(p, arg1, 0);
3116
        break;
3117
#ifdef TARGET_NR_break
3118 3119
    case TARGET_NR_break:
        goto unimplemented;
3120 3121
#endif
#ifdef TARGET_NR_oldstat
3122 3123
    case TARGET_NR_oldstat:
        goto unimplemented;
3124
#endif
3125 3126 3127
    case TARGET_NR_lseek:
        ret = get_errno(lseek(arg1, arg2, arg3));
        break;
3128 3129 3130
#ifdef TARGET_NR_getxpid
    case TARGET_NR_getxpid:
#else
3131
    case TARGET_NR_getpid:
3132
#endif
3133 3134 3135
        ret = get_errno(getpid());
        break;
    case TARGET_NR_mount:
3136 3137 3138 3139 3140 3141
		{
			/* 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);
3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152
                        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);
3153 3154
			break;
		}
3155
#ifdef TARGET_NR_umount
3156
    case TARGET_NR_umount:
3157 3158
        if (!(p = lock_user_string(arg1)))
            goto efault;
3159 3160
        ret = get_errno(umount(p));
        unlock_user(p, arg1, 0);
3161
        break;
3162
#endif
3163
#ifdef TARGET_NR_stime /* not on alpha */
3164 3165
    case TARGET_NR_stime:
        {
3166 3167 3168
            time_t host_time;
            host_time = tgetl(arg1);
            ret = get_errno(stime(&host_time));
3169 3170
        }
        break;
3171
#endif
3172 3173
    case TARGET_NR_ptrace:
        goto unimplemented;
3174
#ifdef TARGET_NR_alarm /* not on alpha */
3175 3176 3177
    case TARGET_NR_alarm:
        ret = alarm(arg1);
        break;
3178
#endif
3179
#ifdef TARGET_NR_oldfstat
3180 3181
    case TARGET_NR_oldfstat:
        goto unimplemented;
3182
#endif
3183
#ifdef TARGET_NR_pause /* not on alpha */
3184 3185 3186
    case TARGET_NR_pause:
        ret = get_errno(pause());
        break;
3187
#endif
3188
#ifdef TARGET_NR_utime
3189
    case TARGET_NR_utime:
3190
        {
3191 3192 3193
            struct utimbuf tbuf, *host_tbuf;
            struct target_utimbuf *target_tbuf;
            if (arg2) {
3194 3195
                if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
                    goto efault;
3196 3197 3198 3199
                tbuf.actime = tswapl(target_tbuf->actime);
                tbuf.modtime = tswapl(target_tbuf->modtime);
                unlock_user_struct(target_tbuf, arg2, 0);
                host_tbuf = &tbuf;
B
bellard 已提交
3200
            } else {
3201
                host_tbuf = NULL;
B
bellard 已提交
3202
            }
3203 3204
            if (!(p = lock_user_string(arg1)))
                goto efault;
3205 3206
            ret = get_errno(utime(p, host_tbuf));
            unlock_user(p, arg1, 0);
3207 3208
        }
        break;
3209
#endif
B
bellard 已提交
3210 3211 3212
    case TARGET_NR_utimes:
        {
            struct timeval *tvp, tv[2];
3213 3214 3215 3216
            if (arg2) {
                target_to_host_timeval(&tv[0], arg2);
                target_to_host_timeval(&tv[1],
                    arg2 + sizeof (struct target_timeval));
B
bellard 已提交
3217 3218 3219 3220
                tvp = tv;
            } else {
                tvp = NULL;
            }
3221 3222
            if (!(p = lock_user_string(arg1)))
                goto efault;
3223 3224
            ret = get_errno(utimes(p, tvp));
            unlock_user(p, arg1, 0);
B
bellard 已提交
3225 3226
        }
        break;
3227
#ifdef TARGET_NR_stty
3228 3229
    case TARGET_NR_stty:
        goto unimplemented;
3230 3231
#endif
#ifdef TARGET_NR_gtty
3232 3233
    case TARGET_NR_gtty:
        goto unimplemented;
3234
#endif
3235
    case TARGET_NR_access:
3236 3237
        if (!(p = lock_user_string(arg1)))
            goto efault;
3238 3239
        ret = get_errno(access(p, arg2));
        unlock_user(p, arg1, 0);
3240
        break;
3241 3242
#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
    case TARGET_NR_faccessat:
3243 3244 3245 3246
        if (!(p = lock_user_string(arg2)))
            goto efault;
        ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
        unlock_user(p, arg2, 0);
3247 3248
        break;
#endif
3249
#ifdef TARGET_NR_nice /* not on alpha */
3250 3251 3252
    case TARGET_NR_nice:
        ret = get_errno(nice(arg1));
        break;
3253
#endif
3254
#ifdef TARGET_NR_ftime
3255 3256
    case TARGET_NR_ftime:
        goto unimplemented;
3257
#endif
3258
    case TARGET_NR_sync:
B
bellard 已提交
3259 3260
        sync();
        ret = 0;
3261 3262 3263 3264 3265
        break;
    case TARGET_NR_kill:
        ret = get_errno(kill(arg1, arg2));
        break;
    case TARGET_NR_rename:
3266 3267 3268 3269
        {
            void *p2;
            p = lock_user_string(arg1);
            p2 = lock_user_string(arg2);
3270 3271 3272 3273
            if (!p || !p2)
                ret = -TARGET_EFAULT;
            else
                ret = get_errno(rename(p, p2));
3274 3275 3276
            unlock_user(p2, arg2, 0);
            unlock_user(p, arg1, 0);
        }
3277
        break;
3278 3279 3280
#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
    case TARGET_NR_renameat:
        {
3281
            void *p2;
3282 3283
            p  = lock_user_string(arg2);
            p2 = lock_user_string(arg4);
3284
            if (!p || !p2)
3285
                ret = -TARGET_EFAULT;
3286 3287
            else
                ret = get_errno(sys_renameat(arg1, p, arg3, p2));
3288 3289
            unlock_user(p2, arg4, 0);
            unlock_user(p, arg2, 0);
3290 3291 3292
        }
        break;
#endif
3293
    case TARGET_NR_mkdir:
3294 3295
        if (!(p = lock_user_string(arg1)))
            goto efault;
3296 3297
        ret = get_errno(mkdir(p, arg2));
        unlock_user(p, arg1, 0);
3298
        break;
3299 3300
#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
    case TARGET_NR_mkdirat:
3301 3302 3303 3304
        if (!(p = lock_user_string(arg2)))
            goto efault;
        ret = get_errno(sys_mkdirat(arg1, p, arg3));
        unlock_user(p, arg2, 0);
3305 3306
        break;
#endif
3307
    case TARGET_NR_rmdir:
3308 3309
        if (!(p = lock_user_string(arg1)))
            goto efault;
3310 3311
        ret = get_errno(rmdir(p));
        unlock_user(p, arg1, 0);
3312 3313 3314 3315 3316 3317
        break;
    case TARGET_NR_dup:
        ret = get_errno(dup(arg1));
        break;
    case TARGET_NR_pipe:
        {
3318 3319
            int host_pipe[2];
            ret = get_errno(pipe(host_pipe));
3320
            if (!is_error(ret)) {
3321
#if defined(TARGET_MIPS)
3322 3323
                CPUMIPSState *env = (CPUMIPSState*)cpu_env;
		env->gpr[3][env->current_tc] = host_pipe[1];
3324 3325
		ret = host_pipe[0];
#else
3326 3327
                tput32(arg1, host_pipe[0]);
                tput32(arg1 + 4, host_pipe[1]);
3328
#endif
3329 3330 3331 3332
            }
        }
        break;
    case TARGET_NR_times:
B
bellard 已提交
3333
        {
3334
            struct target_tms *tmsp;
B
bellard 已提交
3335 3336
            struct tms tms;
            ret = get_errno(times(&tms));
3337
            if (arg1) {
3338 3339 3340
                tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
                if (!tmsp)
                    goto efault;
B
bellard 已提交
3341 3342 3343 3344
                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 已提交
3345
            }
B
bellard 已提交
3346 3347
            if (!is_error(ret))
                ret = host_to_target_clock_t(ret);
B
bellard 已提交
3348 3349
        }
        break;
3350
#ifdef TARGET_NR_prof
3351 3352
    case TARGET_NR_prof:
        goto unimplemented;
3353
#endif
3354
#ifdef TARGET_NR_signal
3355 3356
    case TARGET_NR_signal:
        goto unimplemented;
3357
#endif
3358
    case TARGET_NR_acct:
3359 3360
        if (!(p = lock_user_string(arg1)))
            goto efault;
3361 3362 3363
        ret = get_errno(acct(path(p)));
        unlock_user(p, arg1, 0);
        break;
3364
#ifdef TARGET_NR_umount2 /* not on alpha */
3365
    case TARGET_NR_umount2:
3366 3367
        if (!(p = lock_user_string(arg1)))
            goto efault;
3368 3369
        ret = get_errno(umount2(p, arg2));
        unlock_user(p, arg1, 0);
3370
        break;
3371
#endif
3372
#ifdef TARGET_NR_lock
3373 3374
    case TARGET_NR_lock:
        goto unimplemented;
3375
#endif
3376 3377 3378 3379
    case TARGET_NR_ioctl:
        ret = do_ioctl(arg1, arg2, arg3);
        break;
    case TARGET_NR_fcntl:
B
bellard 已提交
3380
        ret = do_fcntl(arg1, arg2, arg3);
3381
        break;
3382
#ifdef TARGET_NR_mpx
3383 3384
    case TARGET_NR_mpx:
        goto unimplemented;
3385
#endif
3386 3387 3388
    case TARGET_NR_setpgid:
        ret = get_errno(setpgid(arg1, arg2));
        break;
3389
#ifdef TARGET_NR_ulimit
3390 3391
    case TARGET_NR_ulimit:
        goto unimplemented;
3392 3393
#endif
#ifdef TARGET_NR_oldolduname
3394 3395
    case TARGET_NR_oldolduname:
        goto unimplemented;
3396
#endif
3397 3398 3399 3400
    case TARGET_NR_umask:
        ret = get_errno(umask(arg1));
        break;
    case TARGET_NR_chroot:
3401 3402
        if (!(p = lock_user_string(arg1)))
            goto efault;
3403 3404
        ret = get_errno(chroot(p));
        unlock_user(p, arg1, 0);
3405 3406 3407 3408 3409 3410
        break;
    case TARGET_NR_ustat:
        goto unimplemented;
    case TARGET_NR_dup2:
        ret = get_errno(dup2(arg1, arg2));
        break;
3411
#ifdef TARGET_NR_getppid /* not on alpha */
3412 3413 3414
    case TARGET_NR_getppid:
        ret = get_errno(getppid());
        break;
3415
#endif
3416 3417 3418 3419 3420 3421
    case TARGET_NR_getpgrp:
        ret = get_errno(getpgrp());
        break;
    case TARGET_NR_setsid:
        ret = get_errno(setsid());
        break;
3422
#ifdef TARGET_NR_sigaction
3423 3424
    case TARGET_NR_sigaction:
        {
T
ths 已提交
3425
#if !defined(TARGET_MIPS)
3426
            struct target_old_sigaction *old_act;
B
bellard 已提交
3427
            struct target_sigaction act, oact, *pact;
3428
            if (arg2) {
3429 3430
                if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
                    goto efault;
B
bellard 已提交
3431 3432 3433 3434
                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;
3435
                unlock_user_struct(old_act, arg2, 0);
B
bellard 已提交
3436 3437 3438 3439 3440
                pact = &act;
            } else {
                pact = NULL;
            }
            ret = get_errno(do_sigaction(arg1, pact, &oact));
3441
            if (!is_error(ret) && arg3) {
3442 3443
                if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
                    goto efault;
3444 3445 3446 3447 3448
                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 已提交
3449
            }
T
ths 已提交
3450
#else
3451 3452 3453
	    struct target_sigaction act, oact, *pact, *old_act;

	    if (arg2) {
3454 3455
                if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
                    goto efault;
3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467
		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) {
3468 3469
                if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
                    goto efault;
3470 3471 3472 3473 3474 3475 3476 3477
		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 已提交
3478
#endif
3479 3480
        }
        break;
3481
#endif
B
bellard 已提交
3482
    case TARGET_NR_rt_sigaction:
3483 3484 3485 3486
        {
            struct target_sigaction *act;
            struct target_sigaction *oact;

3487 3488 3489 3490
            if (arg2) {
                if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
                    goto efault;
            } else
3491
                act = NULL;
3492 3493 3494 3495 3496 3497
            if (arg3) {
                if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
                    ret = -TARGET_EFAULT;
                    goto rt_sigaction_fail;
                }
            } else
3498 3499
                oact = NULL;
            ret = get_errno(do_sigaction(arg1, act, oact));
3500 3501
	rt_sigaction_fail:
            if (act)
3502
                unlock_user_struct(act, arg2, 0);
3503
            if (oact)
3504 3505
                unlock_user_struct(oact, arg3, 1);
        }
B
bellard 已提交
3506
        break;
3507
#ifdef TARGET_NR_sgetmask /* not on alpha */
3508
    case TARGET_NR_sgetmask:
B
bellard 已提交
3509 3510
        {
            sigset_t cur_set;
3511
            abi_ulong target_set;
B
bellard 已提交
3512 3513 3514 3515 3516
            sigprocmask(0, NULL, &cur_set);
            host_to_target_old_sigset(&target_set, &cur_set);
            ret = target_set;
        }
        break;
3517 3518
#endif
#ifdef TARGET_NR_ssetmask /* not on alpha */
3519
    case TARGET_NR_ssetmask:
B
bellard 已提交
3520 3521
        {
            sigset_t set, oset, cur_set;
3522
            abi_ulong target_set = arg1;
B
bellard 已提交
3523 3524 3525 3526 3527 3528 3529 3530
            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;
3531
#endif
3532
#ifdef TARGET_NR_sigprocmask
B
bellard 已提交
3533 3534 3535 3536
    case TARGET_NR_sigprocmask:
        {
            int how = arg1;
            sigset_t set, oldset, *set_ptr;
3537

3538
            if (arg2) {
B
bellard 已提交
3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549
                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:
3550
                    ret = -TARGET_EINVAL;
B
bellard 已提交
3551 3552
                    goto fail;
                }
3553 3554
                if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
                    goto efault;
3555 3556
                target_to_host_old_sigset(&set, p);
                unlock_user(p, arg2, 0);
B
bellard 已提交
3557 3558 3559 3560 3561 3562
                set_ptr = &set;
            } else {
                how = 0;
                set_ptr = NULL;
            }
            ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
3563
            if (!is_error(ret) && arg3) {
3564 3565
                if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
                    goto efault;
3566 3567
                host_to_target_old_sigset(p, &oldset);
                unlock_user(p, arg3, sizeof(target_sigset_t));
B
bellard 已提交
3568 3569 3570
            }
        }
        break;
3571
#endif
B
bellard 已提交
3572 3573 3574 3575
    case TARGET_NR_rt_sigprocmask:
        {
            int how = arg1;
            sigset_t set, oldset, *set_ptr;
3576

3577
            if (arg2) {
B
bellard 已提交
3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588
                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:
3589
                    ret = -TARGET_EINVAL;
B
bellard 已提交
3590 3591
                    goto fail;
                }
3592 3593
                if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
                    goto efault;
3594 3595
                target_to_host_sigset(&set, p);
                unlock_user(p, arg2, 0);
B
bellard 已提交
3596 3597 3598 3599 3600 3601
                set_ptr = &set;
            } else {
                how = 0;
                set_ptr = NULL;
            }
            ret = get_errno(sigprocmask(how, set_ptr, &oldset));
3602
            if (!is_error(ret) && arg3) {
3603 3604
                if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
                    goto efault;
3605 3606
                host_to_target_sigset(p, &oldset);
                unlock_user(p, arg3, sizeof(target_sigset_t));
B
bellard 已提交
3607 3608 3609
            }
        }
        break;
3610
#ifdef TARGET_NR_sigpending
B
bellard 已提交
3611 3612 3613 3614 3615
    case TARGET_NR_sigpending:
        {
            sigset_t set;
            ret = get_errno(sigpending(&set));
            if (!is_error(ret)) {
3616 3617
                if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
                    goto efault;
3618 3619
                host_to_target_old_sigset(p, &set);
                unlock_user(p, arg1, sizeof(target_sigset_t));
B
bellard 已提交
3620 3621 3622
            }
        }
        break;
3623
#endif
B
bellard 已提交
3624 3625 3626 3627 3628
    case TARGET_NR_rt_sigpending:
        {
            sigset_t set;
            ret = get_errno(sigpending(&set));
            if (!is_error(ret)) {
3629 3630
                if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
                    goto efault;
3631 3632
                host_to_target_sigset(p, &set);
                unlock_user(p, arg1, sizeof(target_sigset_t));
B
bellard 已提交
3633 3634 3635
            }
        }
        break;
3636
#ifdef TARGET_NR_sigsuspend
B
bellard 已提交
3637 3638 3639
    case TARGET_NR_sigsuspend:
        {
            sigset_t set;
3640 3641
            if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
                goto efault;
3642 3643
            target_to_host_old_sigset(&set, p);
            unlock_user(p, arg1, 0);
B
bellard 已提交
3644 3645 3646
            ret = get_errno(sigsuspend(&set));
        }
        break;
3647
#endif
B
bellard 已提交
3648 3649 3650
    case TARGET_NR_rt_sigsuspend:
        {
            sigset_t set;
3651 3652
            if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
                goto efault;
3653 3654
            target_to_host_sigset(&set, p);
            unlock_user(p, arg1, 0);
B
bellard 已提交
3655 3656 3657 3658 3659 3660 3661 3662
            ret = get_errno(sigsuspend(&set));
        }
        break;
    case TARGET_NR_rt_sigtimedwait:
        {
            sigset_t set;
            struct timespec uts, *puts;
            siginfo_t uinfo;
3663

3664 3665
            if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
                goto efault;
3666 3667 3668
            target_to_host_sigset(&set, p);
            unlock_user(p, arg1, 0);
            if (arg3) {
B
bellard 已提交
3669
                puts = &uts;
3670
                target_to_host_timespec(puts, arg3);
B
bellard 已提交
3671 3672 3673 3674
            } else {
                puts = NULL;
            }
            ret = get_errno(sigtimedwait(&set, &uinfo, puts));
3675
            if (!is_error(ret) && arg2) {
3676 3677
                if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_sigset_t), 0)))
                    goto efault;
3678 3679
                host_to_target_siginfo(p, &uinfo);
                unlock_user(p, arg2, sizeof(target_sigset_t));
B
bellard 已提交
3680 3681 3682 3683 3684 3685
            }
        }
        break;
    case TARGET_NR_rt_sigqueueinfo:
        {
            siginfo_t uinfo;
3686 3687
            if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
                goto efault;
3688 3689
            target_to_host_siginfo(&uinfo, p);
            unlock_user(p, arg1, 0);
B
bellard 已提交
3690 3691 3692
            ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
        }
        break;
3693
#ifdef TARGET_NR_sigreturn
B
bellard 已提交
3694 3695 3696 3697
    case TARGET_NR_sigreturn:
        /* NOTE: ret is eax, so not transcoding must be done */
        ret = do_sigreturn(cpu_env);
        break;
3698
#endif
B
bellard 已提交
3699 3700 3701 3702
    case TARGET_NR_rt_sigreturn:
        /* NOTE: ret is eax, so not transcoding must be done */
        ret = do_rt_sigreturn(cpu_env);
        break;
3703
    case TARGET_NR_sethostname:
3704 3705
        if (!(p = lock_user_string(arg1)))
            goto efault;
3706 3707
        ret = get_errno(sethostname(p, arg2));
        unlock_user(p, arg1, 0);
3708 3709
        break;
    case TARGET_NR_setrlimit:
B
bellard 已提交
3710 3711 3712
        {
            /* XXX: convert resource ? */
            int resource = arg1;
3713
            struct target_rlimit *target_rlim;
B
bellard 已提交
3714
            struct rlimit rlim;
3715 3716
            if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
                goto efault;
B
bellard 已提交
3717 3718
            rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
            rlim.rlim_max = tswapl(target_rlim->rlim_max);
3719
            unlock_user_struct(target_rlim, arg2, 0);
B
bellard 已提交
3720 3721 3722
            ret = get_errno(setrlimit(resource, &rlim));
        }
        break;
3723
    case TARGET_NR_getrlimit:
B
bellard 已提交
3724 3725 3726
        {
            /* XXX: convert resource ? */
            int resource = arg1;
3727
            struct target_rlimit *target_rlim;
B
bellard 已提交
3728
            struct rlimit rlim;
3729

B
bellard 已提交
3730 3731
            ret = get_errno(getrlimit(resource, &rlim));
            if (!is_error(ret)) {
3732 3733
                if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
                    goto efault;
3734 3735 3736
                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 已提交
3737 3738 3739
            }
        }
        break;
3740
    case TARGET_NR_getrusage:
B
bellard 已提交
3741 3742 3743 3744
        {
            struct rusage rusage;
            ret = get_errno(getrusage(arg1, &rusage));
            if (!is_error(ret)) {
3745
                host_to_target_rusage(arg2, &rusage);
B
bellard 已提交
3746 3747 3748
            }
        }
        break;
3749 3750 3751 3752 3753
    case TARGET_NR_gettimeofday:
        {
            struct timeval tv;
            ret = get_errno(gettimeofday(&tv, NULL));
            if (!is_error(ret)) {
3754
                host_to_target_timeval(arg1, &tv);
3755 3756 3757 3758 3759 3760
            }
        }
        break;
    case TARGET_NR_settimeofday:
        {
            struct timeval tv;
3761
            target_to_host_timeval(&tv, arg1);
3762 3763 3764
            ret = get_errno(settimeofday(&tv, NULL));
        }
        break;
B
bellard 已提交
3765
#ifdef TARGET_NR_select
3766
    case TARGET_NR_select:
B
bellard 已提交
3767
        {
3768
            struct target_sel_arg_struct *sel;
3769
            abi_ulong inp, outp, exp, tvp;
3770 3771
            long nsel;

3772 3773
            if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
                goto efault;
3774 3775 3776 3777 3778 3779 3780
            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 已提交
3781 3782
        }
        break;
B
bellard 已提交
3783
#endif
3784
    case TARGET_NR_symlink:
3785 3786 3787 3788
        {
            void *p2;
            p = lock_user_string(arg1);
            p2 = lock_user_string(arg2);
3789 3790 3791 3792
            if (!p || !p2)
                ret = -TARGET_EFAULT;
            else
                ret = get_errno(symlink(p, p2));
3793 3794 3795
            unlock_user(p2, arg2, 0);
            unlock_user(p, arg1, 0);
        }
3796
        break;
3797 3798 3799
#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
    case TARGET_NR_symlinkat:
        {
3800
            void *p2;
3801 3802
            p  = lock_user_string(arg1);
            p2 = lock_user_string(arg3);
3803
            if (!p || !p2)
3804
                ret = -TARGET_EFAULT;
3805 3806
            else
                ret = get_errno(sys_symlinkat(p, arg2, p2));
3807 3808
            unlock_user(p2, arg3, 0);
            unlock_user(p, arg1, 0);
3809 3810 3811
        }
        break;
#endif
3812
#ifdef TARGET_NR_oldlstat
3813 3814
    case TARGET_NR_oldlstat:
        goto unimplemented;
3815
#endif
3816
    case TARGET_NR_readlink:
3817 3818 3819
        {
            void *p2;
            p = lock_user_string(arg1);
3820 3821 3822 3823 3824
            p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
            if (!p || !p2)
                ret = -TARGET_EFAULT;
            else
                ret = get_errno(readlink(path(p), p2, arg3));
3825 3826 3827
            unlock_user(p2, arg2, ret);
            unlock_user(p, arg1, 0);
        }
3828
        break;
3829 3830 3831
#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
    case TARGET_NR_readlinkat:
        {
3832
            void *p2;
3833
            p  = lock_user_string(arg2);
3834 3835
            p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
            if (!p || !p2)
3836
        	ret = -TARGET_EFAULT;
3837 3838
            else
                ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
3839 3840
            unlock_user(p2, arg3, ret);
            unlock_user(p, arg2, 0);
3841 3842 3843
        }
        break;
#endif
3844
#ifdef TARGET_NR_uselib
3845 3846
    case TARGET_NR_uselib:
        goto unimplemented;
3847 3848
#endif
#ifdef TARGET_NR_swapon
3849
    case TARGET_NR_swapon:
3850 3851
        if (!(p = lock_user_string(arg1)))
            goto efault;
3852 3853
        ret = get_errno(swapon(p, arg2));
        unlock_user(p, arg1, 0);
3854
        break;
3855
#endif
3856 3857
    case TARGET_NR_reboot:
        goto unimplemented;
3858
#ifdef TARGET_NR_readdir
3859 3860
    case TARGET_NR_readdir:
        goto unimplemented;
3861 3862
#endif
#ifdef TARGET_NR_mmap
3863
    case TARGET_NR_mmap:
3864
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS)
3865
        {
3866 3867
            abi_ulong *v;
            abi_ulong v1, v2, v3, v4, v5, v6;
3868 3869
            if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
                goto efault;
3870 3871 3872 3873 3874 3875 3876
            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);
3877
            ret = get_errno(target_mmap(v1, v2, v3,
B
bellard 已提交
3878 3879
                                        target_to_host_bitmask(v4, mmap_flags_tbl),
                                        v5, v6));
3880 3881
        }
#else
3882 3883
        ret = get_errno(target_mmap(arg1, arg2, arg3,
                                    target_to_host_bitmask(arg4, mmap_flags_tbl),
B
bellard 已提交
3884 3885
                                    arg5,
                                    arg6));
3886
#endif
B
bellard 已提交
3887
        break;
3888
#endif
B
bellard 已提交
3889
#ifdef TARGET_NR_mmap2
B
bellard 已提交
3890
    case TARGET_NR_mmap2:
T
ths 已提交
3891
#if defined(TARGET_SPARC) || defined(TARGET_MIPS)
B
bellard 已提交
3892 3893 3894 3895
#define MMAP_SHIFT 12
#else
#define MMAP_SHIFT TARGET_PAGE_BITS
#endif
3896 3897
        ret = get_errno(target_mmap(arg1, arg2, arg3,
                                    target_to_host_bitmask(arg4, mmap_flags_tbl),
B
bellard 已提交
3898
                                    arg5,
B
bellard 已提交
3899
                                    arg6 << MMAP_SHIFT));
3900
        break;
B
bellard 已提交
3901
#endif
3902
    case TARGET_NR_munmap:
B
bellard 已提交
3903
        ret = get_errno(target_munmap(arg1, arg2));
3904
        break;
B
bellard 已提交
3905
    case TARGET_NR_mprotect:
B
bellard 已提交
3906
        ret = get_errno(target_mprotect(arg1, arg2, arg3));
B
bellard 已提交
3907
        break;
3908
#ifdef TARGET_NR_mremap
B
bellard 已提交
3909
    case TARGET_NR_mremap:
B
bellard 已提交
3910
        ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
B
bellard 已提交
3911
        break;
3912
#endif
3913
        /* ??? msync/mlock/munlock are broken for softmmu.  */
3914
#ifdef TARGET_NR_msync
B
bellard 已提交
3915
    case TARGET_NR_msync:
3916
        ret = get_errno(msync(g2h(arg1), arg2, arg3));
B
bellard 已提交
3917
        break;
3918 3919
#endif
#ifdef TARGET_NR_mlock
B
bellard 已提交
3920
    case TARGET_NR_mlock:
3921
        ret = get_errno(mlock(g2h(arg1), arg2));
B
bellard 已提交
3922
        break;
3923 3924
#endif
#ifdef TARGET_NR_munlock
B
bellard 已提交
3925
    case TARGET_NR_munlock:
3926
        ret = get_errno(munlock(g2h(arg1), arg2));
B
bellard 已提交
3927
        break;
3928 3929
#endif
#ifdef TARGET_NR_mlockall
B
bellard 已提交
3930 3931 3932
    case TARGET_NR_mlockall:
        ret = get_errno(mlockall(arg1));
        break;
3933 3934
#endif
#ifdef TARGET_NR_munlockall
B
bellard 已提交
3935 3936 3937
    case TARGET_NR_munlockall:
        ret = get_errno(munlockall());
        break;
3938
#endif
3939
    case TARGET_NR_truncate:
3940 3941
        if (!(p = lock_user_string(arg1)))
            goto efault;
3942 3943
        ret = get_errno(truncate(p, arg2));
        unlock_user(p, arg1, 0);
3944 3945 3946 3947 3948 3949 3950
        break;
    case TARGET_NR_ftruncate:
        ret = get_errno(ftruncate(arg1, arg2));
        break;
    case TARGET_NR_fchmod:
        ret = get_errno(fchmod(arg1, arg2));
        break;
3951 3952
#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
    case TARGET_NR_fchmodat:
3953 3954 3955 3956
        if (!(p = lock_user_string(arg2)))
            goto efault;
        ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
        unlock_user(p, arg2, 0);
3957 3958
        break;
#endif
3959
    case TARGET_NR_getpriority:
3960 3961 3962 3963
        /* 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);
3964 3965 3966 3967
        break;
    case TARGET_NR_setpriority:
        ret = get_errno(setpriority(arg1, arg2, arg3));
        break;
3968
#ifdef TARGET_NR_profil
3969 3970
    case TARGET_NR_profil:
        goto unimplemented;
3971
#endif
3972
    case TARGET_NR_statfs:
3973 3974
        if (!(p = lock_user_string(arg1)))
            goto efault;
3975 3976
        ret = get_errno(statfs(path(p), &stfs));
        unlock_user(p, arg1, 0);
3977 3978
    convert_statfs:
        if (!is_error(ret)) {
3979
            struct target_statfs *target_stfs;
3980

3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992
            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);
3993
            unlock_user_struct(target_stfs, arg2, 1);
3994 3995 3996
        }
        break;
    case TARGET_NR_fstatfs:
B
bellard 已提交
3997
        ret = get_errno(fstatfs(arg1, &stfs));
3998
        goto convert_statfs;
B
bellard 已提交
3999 4000
#ifdef TARGET_NR_statfs64
    case TARGET_NR_statfs64:
4001 4002
        if (!(p = lock_user_string(arg1)))
            goto efault;
4003 4004
        ret = get_errno(statfs(path(p), &stfs));
        unlock_user(p, arg1, 0);
B
bellard 已提交
4005 4006
    convert_statfs64:
        if (!is_error(ret)) {
4007
            struct target_statfs64 *target_stfs;
4008

4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021
            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 已提交
4022 4023 4024 4025 4026 4027
        }
        break;
    case TARGET_NR_fstatfs64:
        ret = get_errno(fstatfs(arg1, &stfs));
        goto convert_statfs64;
#endif
4028
#ifdef TARGET_NR_ioperm
4029 4030
    case TARGET_NR_ioperm:
        goto unimplemented;
4031
#endif
4032
#ifdef TARGET_NR_socketcall
4033
    case TARGET_NR_socketcall:
4034
        ret = do_socketcall(arg1, arg2);
4035
        break;
4036
#endif
4037 4038
#ifdef TARGET_NR_accept
    case TARGET_NR_accept:
P
pbrook 已提交
4039
        ret = do_accept(arg1, arg2, arg3);
4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053
        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 已提交
4054
        ret = do_getpeername(arg1, arg2, arg3);
4055 4056 4057 4058
        break;
#endif
#ifdef TARGET_NR_getsockname
    case TARGET_NR_getsockname:
P
pbrook 已提交
4059
        ret = do_getsockname(arg1, arg2, arg3);
4060 4061 4062 4063 4064 4065 4066 4067 4068
        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 已提交
4069
        ret = get_errno(listen(arg1, arg2));
4070 4071 4072 4073
        break;
#endif
#ifdef TARGET_NR_recv
    case TARGET_NR_recv:
P
pbrook 已提交
4074
        ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
4075 4076 4077 4078
        break;
#endif
#ifdef TARGET_NR_recvfrom
    case TARGET_NR_recvfrom:
P
pbrook 已提交
4079
        ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
4080 4081 4082 4083 4084 4085 4086 4087 4088
        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 已提交
4089
        ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
4090 4091 4092 4093 4094 4095 4096 4097 4098
        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 已提交
4099
        ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
4100 4101 4102 4103
        break;
#endif
#ifdef TARGET_NR_shutdown
    case TARGET_NR_shutdown:
P
pbrook 已提交
4104
        ret = get_errno(shutdown(arg1, arg2));
4105 4106 4107 4108 4109 4110 4111 4112 4113
        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 已提交
4114
        ret = do_socketpair(arg1, arg2, arg3, arg4);
4115 4116 4117 4118 4119 4120 4121
        break;
#endif
#ifdef TARGET_NR_setsockopt
    case TARGET_NR_setsockopt:
        ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
        break;
#endif
4122

4123
    case TARGET_NR_syslog:
4124 4125
        if (!(p = lock_user_string(arg2)))
            goto efault;
4126 4127
        ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
        unlock_user(p, arg2, 0);
4128 4129
        break;

4130
    case TARGET_NR_setitimer:
B
bellard 已提交
4131 4132 4133
        {
            struct itimerval value, ovalue, *pvalue;

4134
            if (arg2) {
B
bellard 已提交
4135
                pvalue = &value;
4136
                target_to_host_timeval(&pvalue->it_interval,
4137
                                       arg2);
4138
                target_to_host_timeval(&pvalue->it_value,
4139
                                       arg2 + sizeof(struct target_timeval));
B
bellard 已提交
4140 4141 4142 4143
            } else {
                pvalue = NULL;
            }
            ret = get_errno(setitimer(arg1, pvalue, &ovalue));
4144 4145
            if (!is_error(ret) && arg3) {
                host_to_target_timeval(arg3,
B
bellard 已提交
4146
                                       &ovalue.it_interval);
4147
                host_to_target_timeval(arg3 + sizeof(struct target_timeval),
B
bellard 已提交
4148 4149 4150 4151
                                       &ovalue.it_value);
            }
        }
        break;
4152
    case TARGET_NR_getitimer:
B
bellard 已提交
4153 4154
        {
            struct itimerval value;
4155

B
bellard 已提交
4156
            ret = get_errno(getitimer(arg1, &value));
4157 4158
            if (!is_error(ret) && arg2) {
                host_to_target_timeval(arg2,
B
bellard 已提交
4159
                                       &value.it_interval);
4160
                host_to_target_timeval(arg2 + sizeof(struct target_timeval),
B
bellard 已提交
4161 4162 4163 4164
                                       &value.it_value);
            }
        }
        break;
4165
    case TARGET_NR_stat:
4166 4167
        if (!(p = lock_user_string(arg1)))
            goto efault;
4168 4169
        ret = get_errno(stat(path(p), &st));
        unlock_user(p, arg1, 0);
4170 4171
        goto do_stat;
    case TARGET_NR_lstat:
4172 4173
        if (!(p = lock_user_string(arg1)))
            goto efault;
4174 4175
        ret = get_errno(lstat(path(p), &st));
        unlock_user(p, arg1, 0);
4176 4177 4178 4179 4180 4181
        goto do_stat;
    case TARGET_NR_fstat:
        {
            ret = get_errno(fstat(arg1, &st));
        do_stat:
            if (!is_error(ret)) {
4182
                struct target_stat *target_st;
4183

4184 4185
                if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
                    goto efault;
4186
#if defined(TARGET_MIPS) || (defined(TARGET_SPARC64) && !defined(TARGET_ABI32))
4187 4188
                target_st->st_dev = tswap32(st.st_dev);
#else
4189
                target_st->st_dev = tswap16(st.st_dev);
4190
#endif
4191
                target_st->st_ino = tswapl(st.st_ino);
4192
#if defined(TARGET_PPC) || defined(TARGET_MIPS)
4193 4194 4195
                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);
4196
#elif defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
B
blueswir1 已提交
4197 4198 4199
                target_st->st_mode = tswap32(st.st_mode);
                target_st->st_uid = tswap32(st.st_uid);
                target_st->st_gid = tswap32(st.st_gid);
4200
#else
4201
                target_st->st_mode = tswap16(st.st_mode);
4202 4203
                target_st->st_uid = tswap16(st.st_uid);
                target_st->st_gid = tswap16(st.st_gid);
4204
#endif
4205 4206 4207 4208
#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);
4209
#elif defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
B
blueswir1 已提交
4210 4211
                target_st->st_nlink = tswap32(st.st_nlink);
                target_st->st_rdev = tswap32(st.st_rdev);
4212
#else
4213
                target_st->st_nlink = tswap16(st.st_nlink);
4214
                target_st->st_rdev = tswap16(st.st_rdev);
4215
#endif
4216 4217 4218
                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 已提交
4219 4220 4221
                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);
4222
                unlock_user_struct(target_st, arg2, 1);
4223 4224 4225
            }
        }
        break;
4226
#ifdef TARGET_NR_olduname
4227 4228
    case TARGET_NR_olduname:
        goto unimplemented;
4229 4230
#endif
#ifdef TARGET_NR_iopl
4231 4232
    case TARGET_NR_iopl:
        goto unimplemented;
4233
#endif
4234 4235 4236
    case TARGET_NR_vhangup:
        ret = get_errno(vhangup());
        break;
4237
#ifdef TARGET_NR_idle
4238 4239
    case TARGET_NR_idle:
        goto unimplemented;
B
bellard 已提交
4240 4241 4242 4243 4244
#endif
#ifdef TARGET_NR_syscall
    case TARGET_NR_syscall:
    	ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
    	break;
4245
#endif
4246 4247 4248
    case TARGET_NR_wait4:
        {
            int status;
4249
            abi_long status_ptr = arg2;
4250
            struct rusage rusage, *rusage_ptr;
4251
            abi_ulong target_rusage = arg4;
4252 4253 4254 4255 4256 4257 4258
            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)
4259
                    tputl(status_ptr, status);
4260
                if (target_rusage) {
B
bellard 已提交
4261
                    host_to_target_rusage(target_rusage, &rusage);
4262 4263 4264 4265
                }
            }
        }
        break;
4266
#ifdef TARGET_NR_swapoff
4267
    case TARGET_NR_swapoff:
4268 4269
        if (!(p = lock_user_string(arg1)))
            goto efault;
4270 4271
        ret = get_errno(swapoff(p));
        unlock_user(p, arg1, 0);
4272
        break;
4273
#endif
4274
    case TARGET_NR_sysinfo:
B
bellard 已提交
4275
        {
4276
            struct target_sysinfo *target_value;
B
bellard 已提交
4277 4278
            struct sysinfo value;
            ret = get_errno(sysinfo(&value));
4279
            if (!is_error(ret) && arg1)
B
bellard 已提交
4280
            {
4281 4282
                if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
                    goto efault;
B
bellard 已提交
4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296
                __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);
4297
                unlock_user_struct(target_value, arg1, 1);
B
bellard 已提交
4298 4299 4300
            }
        }
        break;
4301
#ifdef TARGET_NR_ipc
4302
    case TARGET_NR_ipc:
4303 4304
	ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
	break;
4305
#endif
4306 4307 4308 4309
    case TARGET_NR_fsync:
        ret = get_errno(fsync(arg1));
        break;
    case TARGET_NR_clone:
B
bellard 已提交
4310 4311
        ret = get_errno(do_fork(cpu_env, arg1, arg2));
        break;
4312 4313 4314
#ifdef __NR_exit_group
        /* new thread calls */
    case TARGET_NR_exit_group:
4315
        gdb_exit(cpu_env, arg1);
4316 4317 4318
        ret = get_errno(exit_group(arg1));
        break;
#endif
4319
    case TARGET_NR_setdomainname:
4320 4321
        if (!(p = lock_user_string(arg1)))
            goto efault;
4322 4323
        ret = get_errno(setdomainname(p, arg2));
        unlock_user(p, arg1, 0);
4324 4325 4326
        break;
    case TARGET_NR_uname:
        /* no need to transcode because we use the linux syscall */
B
bellard 已提交
4327 4328
        {
            struct new_utsname * buf;
4329

4330 4331
            if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
                goto efault;
B
bellard 已提交
4332 4333 4334 4335 4336
            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);
4337 4338 4339
                /* Allow the user to override the reported release.  */
                if (qemu_uname_release && *qemu_uname_release)
                  strcpy (buf->release, qemu_uname_release);
B
bellard 已提交
4340
            }
4341
            unlock_user_struct(buf, arg1, 1);
B
bellard 已提交
4342
        }
4343
        break;
B
bellard 已提交
4344
#ifdef TARGET_I386
4345
    case TARGET_NR_modify_ldt:
4346
        ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
B
bellard 已提交
4347
        break;
4348
#if !defined(TARGET_X86_64)
B
bellard 已提交
4349 4350 4351
    case TARGET_NR_vm86old:
        goto unimplemented;
    case TARGET_NR_vm86:
4352
        ret = do_vm86(cpu_env, arg1, arg2);
B
bellard 已提交
4353
        break;
4354
#endif
B
bellard 已提交
4355
#endif
4356 4357
    case TARGET_NR_adjtimex:
        goto unimplemented;
4358
#ifdef TARGET_NR_create_module
4359
    case TARGET_NR_create_module:
4360
#endif
4361 4362
    case TARGET_NR_init_module:
    case TARGET_NR_delete_module:
4363
#ifdef TARGET_NR_get_kernel_syms
4364
    case TARGET_NR_get_kernel_syms:
4365
#endif
4366 4367 4368 4369 4370 4371 4372 4373 4374
        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;
4375
#ifdef TARGET_NR_bdflush /* not on x86_64 */
4376 4377
    case TARGET_NR_bdflush:
        goto unimplemented;
4378
#endif
4379
#ifdef TARGET_NR_sysfs
4380 4381
    case TARGET_NR_sysfs:
        goto unimplemented;
4382
#endif
4383
    case TARGET_NR_personality:
B
bellard 已提交
4384
        ret = get_errno(personality(arg1));
4385
        break;
4386
#ifdef TARGET_NR_afs_syscall
4387 4388
    case TARGET_NR_afs_syscall:
        goto unimplemented;
4389
#endif
4390
#ifdef TARGET_NR__llseek /* Not on alpha */
4391 4392
    case TARGET_NR__llseek:
        {
B
bellard 已提交
4393 4394
#if defined (__x86_64__)
            ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
4395
            tput64(arg4, ret);
B
bellard 已提交
4396
#else
4397 4398
            int64_t res;
            ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
4399
            tput64(arg4, res);
B
bellard 已提交
4400
#endif
4401 4402
        }
        break;
4403
#endif
4404
    case TARGET_NR_getdents:
4405
#if TARGET_ABI_BITS != 32
4406
        goto unimplemented;
4407
#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
B
bellard 已提交
4408
        {
4409
            struct target_dirent *target_dirp;
B
bellard 已提交
4410
            struct dirent *dirp;
4411
            abi_long count = arg3;
B
bellard 已提交
4412 4413

	    dirp = malloc(count);
4414
	    if (!dirp) {
4415
                ret = -TARGET_ENOMEM;
4416 4417
                goto fail;
            }
4418

B
bellard 已提交
4419 4420 4421 4422 4423 4424 4425 4426 4427 4428
            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;
4429 4430
                if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
                    goto efault;
B
bellard 已提交
4431 4432 4433
		tde = target_dirp;
                while (len > 0) {
                    reclen = de->d_reclen;
4434
		    treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
B
bellard 已提交
4435 4436 4437
                    tde->d_reclen = tswap16(treclen);
                    tde->d_ino = tswapl(de->d_ino);
                    tde->d_off = tswapl(de->d_off);
4438
		    tnamelen = treclen - (2 * sizeof(abi_long) + 2);
B
bellard 已提交
4439 4440
		    if (tnamelen > 256)
                        tnamelen = 256;
B
bellard 已提交
4441
                    /* XXX: may not be correct */
B
bellard 已提交
4442 4443 4444
		    strncpy(tde->d_name, de->d_name, tnamelen);
                    de = (struct dirent *)((char *)de + reclen);
                    len -= reclen;
J
j_mayer 已提交
4445
                    tde = (struct target_dirent *)((char *)tde + treclen);
B
bellard 已提交
4446 4447 4448
		    count1 += treclen;
                }
		ret = count1;
4449
                unlock_user(target_dirp, arg2, ret);
B
bellard 已提交
4450 4451 4452 4453
            }
	    free(dirp);
        }
#else
4454
        {
4455
            struct dirent *dirp;
4456
            abi_long count = arg3;
B
bellard 已提交
4457

4458 4459
            if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
                goto efault;
B
bellard 已提交
4460
            ret = get_errno(sys_getdents(arg1, dirp, count));
4461 4462 4463 4464 4465 4466
            if (!is_error(ret)) {
                struct dirent *de;
                int len = ret;
                int reclen;
                de = dirp;
                while (len > 0) {
B
bellard 已提交
4467
                    reclen = de->d_reclen;
4468 4469
                    if (reclen > len)
                        break;
B
bellard 已提交
4470
                    de->d_reclen = tswap16(reclen);
4471 4472 4473 4474 4475 4476
                    tswapls(&de->d_ino);
                    tswapls(&de->d_off);
                    de = (struct dirent *)((char *)de + reclen);
                    len -= reclen;
                }
            }
4477
            unlock_user(dirp, arg2, ret);
4478
        }
B
bellard 已提交
4479
#endif
4480
        break;
T
ths 已提交
4481
#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
B
bellard 已提交
4482 4483
    case TARGET_NR_getdents64:
        {
4484
            struct dirent64 *dirp;
4485
            abi_long count = arg3;
4486 4487
            if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
                goto efault;
B
bellard 已提交
4488 4489 4490 4491 4492 4493 4494
            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 已提交
4495
                    reclen = de->d_reclen;
B
bellard 已提交
4496 4497
                    if (reclen > len)
                        break;
B
bellard 已提交
4498
                    de->d_reclen = tswap16(reclen);
B
bellard 已提交
4499 4500
                    tswap64s((uint64_t *)&de->d_ino);
                    tswap64s((uint64_t *)&de->d_off);
B
bellard 已提交
4501 4502 4503 4504
                    de = (struct dirent64 *)((char *)de + reclen);
                    len -= reclen;
                }
            }
4505
            unlock_user(dirp, arg2, ret);
B
bellard 已提交
4506 4507
        }
        break;
4508
#endif /* TARGET_NR_getdents64 */
4509
#ifdef TARGET_NR__newselect
4510
    case TARGET_NR__newselect:
4511
        ret = do_select(arg1, arg2, arg3, arg4, arg5);
4512
        break;
4513 4514
#endif
#ifdef TARGET_NR_poll
B
bellard 已提交
4515 4516
    case TARGET_NR_poll:
        {
4517
            struct target_pollfd *target_pfd;
B
bellard 已提交
4518 4519 4520
            unsigned int nfds = arg2;
            int timeout = arg3;
            struct pollfd *pfd;
B
bellard 已提交
4521
            unsigned int i;
B
bellard 已提交
4522

4523 4524 4525
            target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
            if (!target_pfd)
                goto efault;
B
bellard 已提交
4526 4527
            pfd = alloca(sizeof(struct pollfd) * nfds);
            for(i = 0; i < nfds; i++) {
B
bellard 已提交
4528 4529
                pfd[i].fd = tswap32(target_pfd[i].fd);
                pfd[i].events = tswap16(target_pfd[i].events);
B
bellard 已提交
4530 4531 4532 4533
            }
            ret = get_errno(poll(pfd, nfds, timeout));
            if (!is_error(ret)) {
                for(i = 0; i < nfds; i++) {
B
bellard 已提交
4534
                    target_pfd[i].revents = tswap16(pfd[i].revents);
B
bellard 已提交
4535
                }
4536 4537
                ret += nfds * (sizeof(struct target_pollfd)
                               - sizeof(struct pollfd));
B
bellard 已提交
4538
            }
4539
            unlock_user(target_pfd, arg1, ret);
B
bellard 已提交
4540 4541
        }
        break;
4542
#endif
4543
    case TARGET_NR_flock:
B
bellard 已提交
4544 4545 4546
        /* NOTE: the flock constant seems to be the same for every
           Linux platform */
        ret = get_errno(flock(arg1, arg2));
4547 4548 4549 4550 4551 4552 4553
        break;
    case TARGET_NR_readv:
        {
            int count = arg3;
            struct iovec *vec;

            vec = alloca(count * sizeof(struct iovec));
4554
            lock_iovec(VERIFY_WRITE, vec, arg2, count, 0);
4555
            ret = get_errno(readv(arg1, vec, count));
4556
            unlock_iovec(vec, arg2, count, 1);
4557 4558 4559 4560 4561 4562 4563 4564
        }
        break;
    case TARGET_NR_writev:
        {
            int count = arg3;
            struct iovec *vec;

            vec = alloca(count * sizeof(struct iovec));
4565
            lock_iovec(VERIFY_READ, vec, arg2, count, 1);
4566
            ret = get_errno(writev(arg1, vec, count));
4567
            unlock_iovec(vec, arg2, count, 0);
4568 4569 4570 4571 4572
        }
        break;
    case TARGET_NR_getsid:
        ret = get_errno(getsid(arg1));
        break;
4573
#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
4574
    case TARGET_NR_fdatasync:
B
bellard 已提交
4575 4576
        ret = get_errno(fdatasync(arg1));
        break;
4577
#endif
4578
    case TARGET_NR__sysctl:
4579
        /* We don't implement this, but ENOTDIR is always a safe
B
bellard 已提交
4580
           return value. */
4581 4582
        ret = -TARGET_ENOTDIR;
        break;
4583
    case TARGET_NR_sched_setparam:
B
bellard 已提交
4584
        {
4585
            struct sched_param *target_schp;
B
bellard 已提交
4586
            struct sched_param schp;
4587

4588 4589
            if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
                goto efault;
B
bellard 已提交
4590
            schp.sched_priority = tswap32(target_schp->sched_priority);
4591
            unlock_user_struct(target_schp, arg2, 0);
B
bellard 已提交
4592 4593 4594
            ret = get_errno(sched_setparam(arg1, &schp));
        }
        break;
4595
    case TARGET_NR_sched_getparam:
B
bellard 已提交
4596
        {
4597
            struct sched_param *target_schp;
B
bellard 已提交
4598 4599 4600
            struct sched_param schp;
            ret = get_errno(sched_getparam(arg1, &schp));
            if (!is_error(ret)) {
4601 4602
                if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
                    goto efault;
B
bellard 已提交
4603
                target_schp->sched_priority = tswap32(schp.sched_priority);
4604
                unlock_user_struct(target_schp, arg2, 1);
B
bellard 已提交
4605 4606 4607
            }
        }
        break;
4608
    case TARGET_NR_sched_setscheduler:
B
bellard 已提交
4609
        {
4610
            struct sched_param *target_schp;
B
bellard 已提交
4611
            struct sched_param schp;
4612 4613
            if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
                goto efault;
B
bellard 已提交
4614
            schp.sched_priority = tswap32(target_schp->sched_priority);
4615
            unlock_user_struct(target_schp, arg3, 0);
B
bellard 已提交
4616 4617 4618
            ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
        }
        break;
4619
    case TARGET_NR_sched_getscheduler:
B
bellard 已提交
4620 4621
        ret = get_errno(sched_getscheduler(arg1));
        break;
4622 4623 4624 4625
    case TARGET_NR_sched_yield:
        ret = get_errno(sched_yield());
        break;
    case TARGET_NR_sched_get_priority_max:
B
bellard 已提交
4626 4627
        ret = get_errno(sched_get_priority_max(arg1));
        break;
4628
    case TARGET_NR_sched_get_priority_min:
B
bellard 已提交
4629 4630
        ret = get_errno(sched_get_priority_min(arg1));
        break;
4631
    case TARGET_NR_sched_rr_get_interval:
B
bellard 已提交
4632 4633 4634 4635
        {
            struct timespec ts;
            ret = get_errno(sched_rr_get_interval(arg1, &ts));
            if (!is_error(ret)) {
4636
                host_to_target_timespec(arg2, &ts);
B
bellard 已提交
4637 4638 4639
            }
        }
        break;
4640
    case TARGET_NR_nanosleep:
B
bellard 已提交
4641 4642
        {
            struct timespec req, rem;
4643
            target_to_host_timespec(&req, arg1);
B
bellard 已提交
4644
            ret = get_errno(nanosleep(&req, &rem));
4645 4646
            if (is_error(ret) && arg2) {
                host_to_target_timespec(arg2, &rem);
B
bellard 已提交
4647 4648 4649
            }
        }
        break;
4650
#ifdef TARGET_NR_query_module
4651
    case TARGET_NR_query_module:
B
bellard 已提交
4652
        goto unimplemented;
4653 4654
#endif
#ifdef TARGET_NR_nfsservctl
4655
    case TARGET_NR_nfsservctl:
B
bellard 已提交
4656
        goto unimplemented;
4657
#endif
4658
    case TARGET_NR_prctl:
4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672
        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;
            }
4673
        break;
4674
#ifdef TARGET_NR_pread
4675
    case TARGET_NR_pread:
4676 4677
        if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
            goto efault;
4678 4679
        ret = get_errno(pread(arg1, p, arg3, arg4));
        unlock_user(p, arg2, ret);
4680
        break;
4681
    case TARGET_NR_pwrite:
4682 4683
        if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
            goto efault;
4684 4685
        ret = get_errno(pwrite(arg1, p, arg3, arg4));
        unlock_user(p, arg2, 0);
4686
        break;
4687
#endif
4688
    case TARGET_NR_getcwd:
4689 4690
        if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
            goto efault;
4691 4692
        ret = get_errno(sys_getcwd1(p, arg2));
        unlock_user(p, arg1, ret);
4693 4694
        break;
    case TARGET_NR_capget:
B
bellard 已提交
4695
        goto unimplemented;
4696
    case TARGET_NR_capset:
B
bellard 已提交
4697
        goto unimplemented;
4698
    case TARGET_NR_sigaltstack:
4699 4700
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
    defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
4701
        ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
4702 4703
        break;
#else
B
bellard 已提交
4704
        goto unimplemented;
4705
#endif
4706
    case TARGET_NR_sendfile:
B
bellard 已提交
4707
        goto unimplemented;
4708
#ifdef TARGET_NR_getpmsg
4709
    case TARGET_NR_getpmsg:
B
bellard 已提交
4710
        goto unimplemented;
4711 4712
#endif
#ifdef TARGET_NR_putpmsg
4713
    case TARGET_NR_putpmsg:
B
bellard 已提交
4714
        goto unimplemented;
4715
#endif
B
bellard 已提交
4716
#ifdef TARGET_NR_vfork
4717
    case TARGET_NR_vfork:
B
bellard 已提交
4718
        ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0));
4719
        break;
B
bellard 已提交
4720
#endif
4721
#ifdef TARGET_NR_ugetrlimit
4722
    case TARGET_NR_ugetrlimit:
B
bellard 已提交
4723 4724 4725 4726
    {
	struct rlimit rlim;
	ret = get_errno(getrlimit(arg1, &rlim));
	if (!is_error(ret)) {
4727
	    struct target_rlimit *target_rlim;
4728 4729
            if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
                goto efault;
B
bellard 已提交
4730 4731
	    target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
	    target_rlim->rlim_max = tswapl(rlim.rlim_max);
4732
            unlock_user_struct(target_rlim, arg2, 1);
B
bellard 已提交
4733 4734 4735
	}
	break;
    }
4736
#endif
B
bellard 已提交
4737
#ifdef TARGET_NR_truncate64
4738
    case TARGET_NR_truncate64:
4739 4740
        if (!(p = lock_user_string(arg1)))
            goto efault;
4741 4742
	ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
        unlock_user(p, arg1, 0);
B
bellard 已提交
4743
	break;
B
bellard 已提交
4744 4745
#endif
#ifdef TARGET_NR_ftruncate64
4746
    case TARGET_NR_ftruncate64:
P
pbrook 已提交
4747
	ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
B
bellard 已提交
4748
	break;
B
bellard 已提交
4749 4750
#endif
#ifdef TARGET_NR_stat64
4751
    case TARGET_NR_stat64:
4752 4753
        if (!(p = lock_user_string(arg1)))
            goto efault;
4754 4755
        ret = get_errno(stat(path(p), &st));
        unlock_user(p, arg1, 0);
B
bellard 已提交
4756
        goto do_stat64;
B
bellard 已提交
4757 4758
#endif
#ifdef TARGET_NR_lstat64
4759
    case TARGET_NR_lstat64:
4760 4761
        if (!(p = lock_user_string(arg1)))
            goto efault;
4762 4763
        ret = get_errno(lstat(path(p), &st));
        unlock_user(p, arg1, 0);
B
bellard 已提交
4764
        goto do_stat64;
B
bellard 已提交
4765 4766
#endif
#ifdef TARGET_NR_fstat64
4767
    case TARGET_NR_fstat64:
B
bellard 已提交
4768 4769 4770 4771
        {
            ret = get_errno(fstat(arg1, &st));
        do_stat64:
            if (!is_error(ret)) {
P
pbrook 已提交
4772 4773
#ifdef TARGET_ARM
                if (((CPUARMState *)cpu_env)->eabi) {
4774
                    struct target_eabi_stat64 *target_st;
4775 4776 4777

                    if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
                        goto efault;
P
pbrook 已提交
4778
                    memset(target_st, 0, sizeof(struct target_eabi_stat64));
4779 4780
                    __put_user(st.st_dev, &target_st->st_dev);
                    __put_user(st.st_ino, &target_st->st_ino);
P
pbrook 已提交
4781
#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795
                    __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 已提交
4796 4797 4798
                } else
#endif
                {
4799
                    struct target_stat64 *target_st;
4800 4801 4802

                    if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
                        goto efault;
P
pbrook 已提交
4803
                    memset(target_st, 0, sizeof(struct target_stat64));
4804 4805
                    __put_user(st.st_dev, &target_st->st_dev);
                    __put_user(st.st_ino, &target_st->st_ino);
4806
#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
4807
                    __put_user(st.st_ino, &target_st->__st_ino);
P
pbrook 已提交
4808
#endif
4809 4810 4811 4812 4813
                    __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 已提交
4814
                    /* XXX: better use of kernel struct */
4815 4816 4817 4818 4819 4820 4821
                    __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 已提交
4822
                }
B
bellard 已提交
4823 4824 4825
            }
        }
        break;
B
bellard 已提交
4826
#endif
4827 4828
#ifdef USE_UID16
    case TARGET_NR_lchown:
4829 4830
        if (!(p = lock_user_string(arg1)))
            goto efault;
4831 4832
        ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
        unlock_user(p, arg1, 0);
4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854
        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;
4855
            uint16_t *target_grouplist;
4856 4857 4858 4859 4860 4861
            gid_t *grouplist;
            int i;

            grouplist = alloca(gidsetsize * sizeof(gid_t));
            ret = get_errno(getgroups(gidsetsize, grouplist));
            if (!is_error(ret)) {
4862 4863 4864
                target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
                if (!target_grouplist)
                    goto efault;
4865 4866
                for(i = 0;i < gidsetsize; i++)
                    target_grouplist[i] = tswap16(grouplist[i]);
4867
                unlock_user(target_grouplist, arg2, gidsetsize * 2);
4868 4869 4870 4871 4872 4873
            }
        }
        break;
    case TARGET_NR_setgroups:
        {
            int gidsetsize = arg1;
4874
            uint16_t *target_grouplist;
4875 4876 4877 4878
            gid_t *grouplist;
            int i;

            grouplist = alloca(gidsetsize * sizeof(gid_t));
4879 4880 4881 4882 4883
            target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
            if (!target_grouplist) {
                ret = -TARGET_EFAULT;
                goto fail;
            }
4884 4885
            for(i = 0;i < gidsetsize; i++)
                grouplist[i] = tswap16(target_grouplist[i]);
4886
            unlock_user(target_grouplist, arg2, 0);
4887 4888 4889 4890 4891 4892
            ret = get_errno(setgroups(gidsetsize, grouplist));
        }
        break;
    case TARGET_NR_fchown:
        ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
        break;
4893 4894
#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
    case TARGET_NR_fchownat:
4895 4896 4897 4898
        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);
4899 4900
        break;
#endif
4901 4902
#ifdef TARGET_NR_setresuid
    case TARGET_NR_setresuid:
4903 4904
        ret = get_errno(setresuid(low2highuid(arg1),
                                  low2highuid(arg2),
4905 4906 4907 4908 4909 4910
                                  low2highuid(arg3)));
        break;
#endif
#ifdef TARGET_NR_getresuid
    case TARGET_NR_getresuid:
        {
4911
            uid_t ruid, euid, suid;
4912 4913
            ret = get_errno(getresuid(&ruid, &euid, &suid));
            if (!is_error(ret)) {
4914 4915 4916
                tput16(arg1, tswap16(high2lowuid(ruid)));
                tput16(arg2, tswap16(high2lowuid(euid)));
                tput16(arg3, tswap16(high2lowuid(suid)));
4917 4918 4919 4920 4921 4922
            }
        }
        break;
#endif
#ifdef TARGET_NR_getresgid
    case TARGET_NR_setresgid:
4923 4924
        ret = get_errno(setresgid(low2highgid(arg1),
                                  low2highgid(arg2),
4925 4926 4927 4928 4929 4930
                                  low2highgid(arg3)));
        break;
#endif
#ifdef TARGET_NR_getresgid
    case TARGET_NR_getresgid:
        {
4931
            gid_t rgid, egid, sgid;
4932 4933
            ret = get_errno(getresgid(&rgid, &egid, &sgid));
            if (!is_error(ret)) {
4934 4935 4936
                tput16(arg1, tswap16(high2lowgid(rgid)));
                tput16(arg2, tswap16(high2lowgid(egid)));
                tput16(arg3, tswap16(high2lowgid(sgid)));
4937 4938 4939 4940 4941
            }
        }
        break;
#endif
    case TARGET_NR_chown:
4942 4943
        if (!(p = lock_user_string(arg1)))
            goto efault;
4944 4945
        ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
        unlock_user(p, arg1, 0);
4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960
        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 已提交
4961
#ifdef TARGET_NR_lchown32
4962
    case TARGET_NR_lchown32:
4963 4964
        if (!(p = lock_user_string(arg1)))
            goto efault;
4965 4966
        ret = get_errno(lchown(p, arg2, arg3));
        unlock_user(p, arg1, 0);
B
bellard 已提交
4967
        break;
B
bellard 已提交
4968 4969
#endif
#ifdef TARGET_NR_getuid32
4970
    case TARGET_NR_getuid32:
B
bellard 已提交
4971 4972
        ret = get_errno(getuid());
        break;
B
bellard 已提交
4973 4974
#endif
#ifdef TARGET_NR_getgid32
4975
    case TARGET_NR_getgid32:
B
bellard 已提交
4976 4977
        ret = get_errno(getgid());
        break;
B
bellard 已提交
4978 4979
#endif
#ifdef TARGET_NR_geteuid32
4980
    case TARGET_NR_geteuid32:
B
bellard 已提交
4981 4982
        ret = get_errno(geteuid());
        break;
B
bellard 已提交
4983 4984
#endif
#ifdef TARGET_NR_getegid32
4985
    case TARGET_NR_getegid32:
B
bellard 已提交
4986 4987
        ret = get_errno(getegid());
        break;
B
bellard 已提交
4988 4989
#endif
#ifdef TARGET_NR_setreuid32
4990
    case TARGET_NR_setreuid32:
B
bellard 已提交
4991 4992
        ret = get_errno(setreuid(arg1, arg2));
        break;
B
bellard 已提交
4993 4994
#endif
#ifdef TARGET_NR_setregid32
4995
    case TARGET_NR_setregid32:
B
bellard 已提交
4996 4997
        ret = get_errno(setregid(arg1, arg2));
        break;
B
bellard 已提交
4998 4999
#endif
#ifdef TARGET_NR_getgroups32
5000
    case TARGET_NR_getgroups32:
B
bellard 已提交
5001 5002
        {
            int gidsetsize = arg1;
5003
            uint32_t *target_grouplist;
B
bellard 已提交
5004 5005 5006 5007 5008 5009
            gid_t *grouplist;
            int i;

            grouplist = alloca(gidsetsize * sizeof(gid_t));
            ret = get_errno(getgroups(gidsetsize, grouplist));
            if (!is_error(ret)) {
5010 5011 5012 5013 5014
                target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
                if (!target_grouplist) {
                    ret = -TARGET_EFAULT;
                    goto fail;
                }
B
bellard 已提交
5015
                for(i = 0;i < gidsetsize; i++)
5016 5017
                    target_grouplist[i] = tswap32(grouplist[i]);
                unlock_user(target_grouplist, arg2, gidsetsize * 4);
B
bellard 已提交
5018 5019 5020
            }
        }
        break;
B
bellard 已提交
5021 5022
#endif
#ifdef TARGET_NR_setgroups32
5023
    case TARGET_NR_setgroups32:
B
bellard 已提交
5024 5025
        {
            int gidsetsize = arg1;
5026
            uint32_t *target_grouplist;
B
bellard 已提交
5027 5028
            gid_t *grouplist;
            int i;
5029

B
bellard 已提交
5030
            grouplist = alloca(gidsetsize * sizeof(gid_t));
5031 5032 5033 5034 5035
            target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
            if (!target_grouplist) {
                ret = -TARGET_EFAULT;
                goto fail;
            }
B
bellard 已提交
5036
            for(i = 0;i < gidsetsize; i++)
5037 5038
                grouplist[i] = tswap32(target_grouplist[i]);
            unlock_user(target_grouplist, arg2, 0);
B
bellard 已提交
5039 5040 5041
            ret = get_errno(setgroups(gidsetsize, grouplist));
        }
        break;
B
bellard 已提交
5042 5043
#endif
#ifdef TARGET_NR_fchown32
5044
    case TARGET_NR_fchown32:
B
bellard 已提交
5045 5046
        ret = get_errno(fchown(arg1, arg2, arg3));
        break;
B
bellard 已提交
5047 5048
#endif
#ifdef TARGET_NR_setresuid32
5049
    case TARGET_NR_setresuid32:
B
bellard 已提交
5050 5051
        ret = get_errno(setresuid(arg1, arg2, arg3));
        break;
B
bellard 已提交
5052 5053
#endif
#ifdef TARGET_NR_getresuid32
5054
    case TARGET_NR_getresuid32:
B
bellard 已提交
5055
        {
5056
            uid_t ruid, euid, suid;
B
bellard 已提交
5057 5058
            ret = get_errno(getresuid(&ruid, &euid, &suid));
            if (!is_error(ret)) {
5059 5060 5061
                tput32(arg1, tswap32(ruid));
                tput32(arg2, tswap32(euid));
                tput32(arg3, tswap32(suid));
B
bellard 已提交
5062 5063 5064
            }
        }
        break;
B
bellard 已提交
5065 5066
#endif
#ifdef TARGET_NR_setresgid32
5067
    case TARGET_NR_setresgid32:
B
bellard 已提交
5068 5069
        ret = get_errno(setresgid(arg1, arg2, arg3));
        break;
B
bellard 已提交
5070 5071
#endif
#ifdef TARGET_NR_getresgid32
5072
    case TARGET_NR_getresgid32:
B
bellard 已提交
5073
        {
5074
            gid_t rgid, egid, sgid;
B
bellard 已提交
5075 5076
            ret = get_errno(getresgid(&rgid, &egid, &sgid));
            if (!is_error(ret)) {
5077 5078 5079
                tput32(arg1, tswap32(rgid));
                tput32(arg2, tswap32(egid));
                tput32(arg3, tswap32(sgid));
B
bellard 已提交
5080 5081 5082
            }
        }
        break;
B
bellard 已提交
5083 5084
#endif
#ifdef TARGET_NR_chown32
5085
    case TARGET_NR_chown32:
5086 5087
        if (!(p = lock_user_string(arg1)))
            goto efault;
5088 5089
        ret = get_errno(chown(p, arg2, arg3));
        unlock_user(p, arg1, 0);
B
bellard 已提交
5090
        break;
B
bellard 已提交
5091 5092
#endif
#ifdef TARGET_NR_setuid32
5093
    case TARGET_NR_setuid32:
B
bellard 已提交
5094 5095
        ret = get_errno(setuid(arg1));
        break;
B
bellard 已提交
5096 5097
#endif
#ifdef TARGET_NR_setgid32
5098
    case TARGET_NR_setgid32:
B
bellard 已提交
5099 5100
        ret = get_errno(setgid(arg1));
        break;
B
bellard 已提交
5101 5102
#endif
#ifdef TARGET_NR_setfsuid32
5103
    case TARGET_NR_setfsuid32:
B
bellard 已提交
5104 5105
        ret = get_errno(setfsuid(arg1));
        break;
B
bellard 已提交
5106 5107
#endif
#ifdef TARGET_NR_setfsgid32
5108
    case TARGET_NR_setfsgid32:
B
bellard 已提交
5109 5110
        ret = get_errno(setfsgid(arg1));
        break;
B
bellard 已提交
5111
#endif
5112

5113
    case TARGET_NR_pivot_root:
B
bellard 已提交
5114
        goto unimplemented;
B
bellard 已提交
5115
#ifdef TARGET_NR_mincore
5116
    case TARGET_NR_mincore:
B
bellard 已提交
5117
        goto unimplemented;
B
bellard 已提交
5118 5119
#endif
#ifdef TARGET_NR_madvise
5120
    case TARGET_NR_madvise:
5121 5122 5123 5124 5125 5126
        /* 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 已提交
5127
#endif
5128
#if TARGET_ABI_BITS == 32
5129
    case TARGET_NR_fcntl64:
B
bellard 已提交
5130
    {
T
ths 已提交
5131
	int cmd;
B
bellard 已提交
5132
	struct flock64 fl;
5133
	struct target_flock64 *target_fl;
P
pbrook 已提交
5134
#ifdef TARGET_ARM
5135
	struct target_eabi_flock64 *target_efl;
P
pbrook 已提交
5136
#endif
B
bellard 已提交
5137

T
ths 已提交
5138 5139 5140
        switch(arg2){
        case TARGET_F_GETLK64:
            cmd = F_GETLK64;
5141
            break;
T
ths 已提交
5142 5143
        case TARGET_F_SETLK64:
            cmd = F_SETLK64;
5144
            break;
T
ths 已提交
5145 5146
        case TARGET_F_SETLKW64:
            cmd = F_SETLK64;
5147
            break;
T
ths 已提交
5148 5149
        default:
            cmd = arg2;
5150
            break;
T
ths 已提交
5151 5152
        }

B
bellard 已提交
5153
        switch(arg2) {
T
ths 已提交
5154
        case TARGET_F_GETLK64:
T
ths 已提交
5155 5156
#ifdef TARGET_ARM
            if (((CPUARMState *)cpu_env)->eabi) {
B
bellard 已提交
5157 5158
                if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1)) 
                    goto efault;
T
ths 已提交
5159 5160 5161 5162 5163 5164 5165 5166 5167
                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 已提交
5168 5169
                if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1)) 
                    goto efault;
T
ths 已提交
5170 5171 5172 5173 5174 5175 5176
                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 已提交
5177
            ret = get_errno(fcntl(arg1, cmd, &fl));
B
bellard 已提交
5178
	    if (ret == 0) {
P
pbrook 已提交
5179 5180
#ifdef TARGET_ARM
                if (((CPUARMState *)cpu_env)->eabi) {
B
bellard 已提交
5181 5182
                    if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0)) 
                        goto efault;
P
pbrook 已提交
5183 5184 5185 5186 5187
                    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);
5188
                    unlock_user_struct(target_efl, arg3, 1);
P
pbrook 已提交
5189 5190 5191
                } else
#endif
                {
B
bellard 已提交
5192 5193
                    if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0)) 
                        goto efault;
P
pbrook 已提交
5194 5195 5196 5197 5198
                    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);
5199
                    unlock_user_struct(target_fl, arg3, 1);
P
pbrook 已提交
5200
                }
B
bellard 已提交
5201 5202 5203
	    }
	    break;

T
ths 已提交
5204 5205
        case TARGET_F_SETLK64:
        case TARGET_F_SETLKW64:
P
pbrook 已提交
5206 5207
#ifdef TARGET_ARM
            if (((CPUARMState *)cpu_env)->eabi) {
B
bellard 已提交
5208 5209
                if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1)) 
                    goto efault;
P
pbrook 已提交
5210 5211 5212 5213 5214
                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);
5215
                unlock_user_struct(target_efl, arg3, 0);
P
pbrook 已提交
5216 5217 5218
            } else
#endif
            {
B
bellard 已提交
5219 5220
                if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1)) 
                    goto efault;
P
pbrook 已提交
5221 5222 5223 5224 5225
                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);
5226
                unlock_user_struct(target_fl, arg3, 0);
P
pbrook 已提交
5227
            }
T
ths 已提交
5228
            ret = get_errno(fcntl(arg1, cmd, &fl));
B
bellard 已提交
5229
	    break;
B
bellard 已提交
5230
        default:
B
bellard 已提交
5231
            ret = do_fcntl(arg1, cmd, arg3);
B
bellard 已提交
5232 5233
            break;
        }
B
bellard 已提交
5234 5235
	break;
    }
B
bellard 已提交
5236
#endif
5237 5238 5239 5240 5241 5242
#ifdef TARGET_NR_cacheflush
    case TARGET_NR_cacheflush:
        /* self-modifying code is handled automatically, so nothing needed */
        ret = 0;
        break;
#endif
5243
#ifdef TARGET_NR_security
5244 5245
    case TARGET_NR_security:
        goto unimplemented;
B
bellard 已提交
5246 5247 5248 5249 5250
#endif
#ifdef TARGET_NR_getpagesize
    case TARGET_NR_getpagesize:
        ret = TARGET_PAGE_SIZE;
        break;
5251
#endif
5252 5253 5254
    case TARGET_NR_gettid:
        ret = get_errno(gettid());
        break;
5255
#ifdef TARGET_NR_readahead
5256
    case TARGET_NR_readahead:
B
bellard 已提交
5257
        goto unimplemented;
5258
#endif
5259
#ifdef TARGET_NR_setxattr
5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271
    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 已提交
5272
        goto unimplemented_nowarn;
5273 5274
#endif
#ifdef TARGET_NR_set_thread_area
B
bellard 已提交
5275
    case TARGET_NR_set_thread_area:
B
bellard 已提交
5276
#if defined(TARGET_MIPS)
5277 5278 5279
      ((CPUMIPSState *) cpu_env)->tls_value = arg1;
      ret = 0;
      break;
B
bellard 已提交
5280 5281 5282
#elif defined(TARGET_I386) && defined(TARGET_ABI32)
      ret = do_set_thread_area(cpu_env, arg1);
      break;
5283 5284 5285 5286 5287
#else
      goto unimplemented_nowarn;
#endif
#endif
#ifdef TARGET_NR_get_thread_area
B
bellard 已提交
5288
    case TARGET_NR_get_thread_area:
B
bellard 已提交
5289 5290 5291
#if defined(TARGET_I386) && defined(TARGET_ABI32)
        ret = do_get_thread_area(cpu_env, arg1);
#else
B
bellard 已提交
5292
        goto unimplemented_nowarn;
B
bellard 已提交
5293
#endif
B
bellard 已提交
5294
#endif
B
bellard 已提交
5295 5296 5297
#ifdef TARGET_NR_getdomainname
    case TARGET_NR_getdomainname:
        goto unimplemented_nowarn;
5298
#endif
5299

5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322
#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

5323 5324
#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
    case TARGET_NR_set_tid_address:
5325 5326
        ret = get_errno(set_tid_address((int *)g2h(arg1)));
        break;
5327 5328
#endif

T
ths 已提交
5329
#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
T
ths 已提交
5330 5331 5332 5333 5334
    case TARGET_NR_tkill:
        ret = get_errno(sys_tkill((int)arg1, (int)arg2));
        break;
#endif

T
ths 已提交
5335
#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
T
ths 已提交
5336 5337 5338 5339 5340
    case TARGET_NR_tgkill:
	ret = get_errno(sys_tgkill((int)arg1, (int)arg2, (int)arg3));
	break;
#endif

5341 5342 5343 5344 5345
#ifdef TARGET_NR_set_robust_list
    case TARGET_NR_set_robust_list:
	goto unimplemented_nowarn;
#endif

5346 5347 5348 5349 5350 5351 5352 5353 5354
#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 {
5355
                if (!(p = lock_user_string(arg2))) {
5356
                    ret = -TARGET_EFAULT;
5357 5358 5359 5360
                    goto fail;
                }
                ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
                unlock_user(p, arg2, 0);
5361 5362 5363 5364 5365
            }
        }
	break;
#endif

5366 5367
    default:
    unimplemented:
B
bellard 已提交
5368
        gemu_log("qemu: Unsupported syscall: %d\n", num);
5369
#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname) || defined(TARGET_NR_set_robust_list)
B
bellard 已提交
5370
    unimplemented_nowarn:
B
bellard 已提交
5371
#endif
5372
        ret = -TARGET_ENOSYS;
5373 5374
        break;
    }
5375
fail:
B
bellard 已提交
5376 5377 5378
#ifdef DEBUG
    gemu_log(" = %ld\n", ret);
#endif
5379 5380
    if(do_strace)
        print_syscall_ret(num, ret);
5381
    return ret;
5382 5383 5384
efault:
    ret = -TARGET_EFAULT;
    goto fail;
5385
}