syscall.c 119.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 *  Linux syscalls
 * 
 *  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 31 32 33 34 35 36 37 38 39 40 41
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/mount.h>
#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 已提交
42
#include <sys/poll.h>
B
bellard 已提交
43
#include <sys/times.h>
44
#include <sys/shm.h>
B
bellard 已提交
45
#include <sys/statfs.h>
46
#include <utime.h>
B
bellard 已提交
47
#include <sys/sysinfo.h>
B
bellard 已提交
48
//#include <sys/user.h>
49
#include <netinet/ip.h>
B
bellard 已提交
50
#include <netinet/tcp.h>
51 52 53 54

#define termios host_termios
#define winsize host_winsize
#define termio host_termio
B
bellard 已提交
55 56 57
#define sgttyb host_sgttyb /* same as target */
#define tchars host_tchars /* same as target */
#define ltchars host_ltchars /* same as target */
58 59 60 61 62 63 64

#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 已提交
65
#include <linux/dirent.h>
B
bellard 已提交
66
#include <linux/kd.h>
67

B
bellard 已提交
68
#include "qemu.h"
69

B
bellard 已提交
70
//#define DEBUG
71

P
pbrook 已提交
72 73
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
    || defined(TARGET_M68K)
74 75 76 77
/* 16 bit uid wrappers emulation */
#define USE_UID16
#endif

B
bellard 已提交
78 79 80 81
//#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])

82 83 84 85 86 87 88

#undef _syscall0
#undef _syscall1
#undef _syscall2
#undef _syscall3
#undef _syscall4
#undef _syscall5
B
bellard 已提交
89
#undef _syscall6
90

B
bellard 已提交
91 92 93 94 95
#define _syscall0(type,name)		\
type name (void)			\
{					\
	return syscall(__NR_##name);	\
}
96

B
bellard 已提交
97 98 99 100
#define _syscall1(type,name,type1,arg1)		\
type name (type1 arg1)				\
{						\
	return syscall(__NR_##name, arg1);	\
101 102
}

B
bellard 已提交
103 104 105 106
#define _syscall2(type,name,type1,arg1,type2,arg2)	\
type name (type1 arg1,type2 arg2)			\
{							\
	return syscall(__NR_##name, arg1, arg2);	\
107 108
}

B
bellard 已提交
109 110 111 112
#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);		\
113 114
}

B
bellard 已提交
115 116 117 118
#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);			\
119 120
}

B
bellard 已提交
121 122 123 124 125
#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);		\
126 127
}

B
bellard 已提交
128 129 130 131 132 133

#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);	\
134
}
B
bellard 已提交
135

136

137
#define __NR_sys_uname __NR_uname
B
bellard 已提交
138 139
#define __NR_sys_getcwd1 __NR_getcwd
#define __NR_sys_getdents __NR_getdents
B
bellard 已提交
140
#define __NR_sys_getdents64 __NR_getdents64
B
bellard 已提交
141
#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
142

143
#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
B
bellard 已提交
144 145 146
#define __NR__llseek __NR_lseek
#endif

B
bellard 已提交
147
#ifdef __NR_gettid
148
_syscall0(int, gettid)
B
bellard 已提交
149 150 151 152 153
#else
static int gettid(void) {
    return -ENOSYS;
}
#endif
154
_syscall1(int,sys_uname,struct new_utsname *,buf)
B
bellard 已提交
155 156
_syscall2(int,sys_getcwd1,char *,buf,size_t,size)
_syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count);
B
bellard 已提交
157
_syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count);
158 159
_syscall5(int, _llseek,  uint,  fd, ulong, hi, ulong, lo,
          loff_t *, res, uint, wh);
B
bellard 已提交
160
_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
161 162 163
#ifdef __NR_exit_group
_syscall1(int,exit_group,int,error_code)
#endif
B
bellard 已提交
164 165

extern int personality(int);
B
bellard 已提交
166 167 168
extern int flock(int, int);
extern int setfsuid(int);
extern int setfsgid(int);
B
bellard 已提交
169 170 171 172
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 已提交
173
extern int setgroups(int, gid_t *);
174 175 176 177 178 179 180 181 182 183 184 185 186 187

static inline long get_errno(long ret)
{
    if (ret == -1)
        return -errno;
    else
        return ret;
}

static inline int is_error(long ret)
{
    return (unsigned long)ret >= (unsigned long)(-4096);
}

188 189
static target_ulong target_brk;
static target_ulong target_original_brk;
190

191
void target_set_brk(target_ulong new_brk)
192
{
193
    target_original_brk = target_brk = new_brk;
194 195
}

196
long do_brk(target_ulong new_brk)
197
{
198
    target_ulong brk_page;
199 200 201 202
    long mapped_addr;
    int	new_alloc_size;

    if (!new_brk)
203
        return target_brk;
204 205 206
    if (new_brk < target_original_brk)
        return -ENOMEM;
    
207
    brk_page = HOST_PAGE_ALIGN(target_brk);
208 209 210 211

    /* If the new brk is less than this, set it and we're done... */
    if (new_brk < brk_page) {
	target_brk = new_brk;
212
    	return target_brk;
213 214 215
    }

    /* We need to allocate more memory after the brk... */
B
bellard 已提交
216
    new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
217
    mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size, 
B
bellard 已提交
218 219
                                        PROT_READ|PROT_WRITE,
                                        MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
220 221 222 223
    if (is_error(mapped_addr)) {
	return mapped_addr;
    } else {
	target_brk = new_brk;
224
    	return target_brk;
225 226 227 228 229 230
    }
}

static inline fd_set *target_to_host_fds(fd_set *fds, 
                                         target_long *target_fds, int n)
{
B
bellard 已提交
231
#if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN)
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
    return (fd_set *)target_fds;
#else
    int i, b;
    if (target_fds) {
        FD_ZERO(fds);
        for(i = 0;i < n; i++) {
            b = (tswapl(target_fds[i / TARGET_LONG_BITS]) >>
                 (i & (TARGET_LONG_BITS - 1))) & 1;
            if (b)
                FD_SET(i, fds);
        }
        return fds;
    } else {
        return NULL;
    }
#endif
}

static inline void host_to_target_fds(target_long *target_fds, 
                                      fd_set *fds, int n)
{
B
bellard 已提交
253
#if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN)
254 255 256 257 258 259
    /* nothing to do */
#else
    int i, nw, j, k;
    target_long v;

    if (target_fds) {
260
        nw = (n + TARGET_LONG_BITS - 1) / TARGET_LONG_BITS;
261 262 263 264 265 266 267 268 269 270 271 272 273
        k = 0;
        for(i = 0;i < nw; i++) {
            v = 0;
            for(j = 0; j < TARGET_LONG_BITS; j++) {
                v |= ((FD_ISSET(k, fds) != 0) << j);
                k++;
            }
            target_fds[i] = tswapl(v);
        }
    }
#endif
}

B
bellard 已提交
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
#if defined(__alpha__)
#define HOST_HZ 1024
#else
#define HOST_HZ 100
#endif

static inline long host_to_target_clock_t(long ticks)
{
#if HOST_HZ == TARGET_HZ
    return ticks;
#else
    return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
#endif
}

289
static inline void host_to_target_rusage(target_ulong target_addr,
B
bellard 已提交
290 291
                                         const struct rusage *rusage)
{
292 293 294
    struct target_rusage *target_rusage;

    lock_user_struct(target_rusage, target_addr, 0);
B
bellard 已提交
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
    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);
313
    unlock_user_struct(target_rusage, target_addr, 1);
B
bellard 已提交
314 315
}

316 317
static inline void target_to_host_timeval(struct timeval *tv,
                                          target_ulong target_addr)
318
{
319 320 321
    struct target_timeval *target_tv;

    lock_user_struct(target_tv, target_addr, 1);
B
bellard 已提交
322 323
    tv->tv_sec = tswapl(target_tv->tv_sec);
    tv->tv_usec = tswapl(target_tv->tv_usec);
324
    unlock_user_struct(target_tv, target_addr, 0);
325 326
}

327
static inline void host_to_target_timeval(target_ulong target_addr,
B
bellard 已提交
328
                                          const struct timeval *tv)
329
{
330 331 332
    struct target_timeval *target_tv;

    lock_user_struct(target_tv, target_addr, 0);
B
bellard 已提交
333 334
    target_tv->tv_sec = tswapl(tv->tv_sec);
    target_tv->tv_usec = tswapl(tv->tv_usec);
335
    unlock_user_struct(target_tv, target_addr, 1);
336 337 338 339
}


static long do_select(long n, 
340 341
                      target_ulong rfd_p, target_ulong wfd_p, 
                      target_ulong efd_p, target_ulong target_tv)
342 343 344
{
    fd_set rfds, wfds, efds;
    fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
345
    target_long *target_rfds, *target_wfds, *target_efds;
346 347
    struct timeval tv, *tv_ptr;
    long ret;
348
    int ok;
349

350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
    if (rfd_p) {
        target_rfds = lock_user(rfd_p, sizeof(target_long) * n, 1);
        rfds_ptr = target_to_host_fds(&rfds, target_rfds, n);
    } else {
        target_rfds = NULL;
        rfds_ptr = NULL;
    }
    if (wfd_p) {
        target_wfds = lock_user(wfd_p, sizeof(target_long) * n, 1);
        wfds_ptr = target_to_host_fds(&wfds, target_wfds, n);
    } else {
        target_wfds = NULL;
        wfds_ptr = NULL;
    }
    if (efd_p) {
        target_efds = lock_user(efd_p, sizeof(target_long) * n, 1);
        efds_ptr = target_to_host_fds(&efds, target_efds, n);
    } else {
        target_efds = NULL;
        efds_ptr = NULL;
    }
371 372
            
    if (target_tv) {
B
bellard 已提交
373
        target_to_host_timeval(&tv, target_tv);
374 375 376 377 378
        tv_ptr = &tv;
    } else {
        tv_ptr = NULL;
    }
    ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
379 380 381
    ok = !is_error(ret);

    if (ok) {
382 383 384 385 386
        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 已提交
387
            host_to_target_timeval(target_tv, &tv);
388 389
        }
    }
390 391 392 393 394 395 396
    if (target_rfds)
        unlock_user(target_rfds, rfd_p, ok ? sizeof(target_long) * n : 0);
    if (target_wfds)
        unlock_user(target_wfds, wfd_p, ok ? sizeof(target_long) * n : 0);
    if (target_efds)
        unlock_user(target_efds, efd_p, ok ? sizeof(target_long) * n : 0);

397 398 399
    return ret;
}

B
bellard 已提交
400
static inline void target_to_host_sockaddr(struct sockaddr *addr,
401
                                           target_ulong target_addr,
B
bellard 已提交
402 403
                                           socklen_t len)
{
404 405 406 407 408 409
    struct target_sockaddr *target_saddr;

    target_saddr = lock_user(target_addr, len, 1);
    memcpy(addr, target_saddr, len);
    addr->sa_family = tswap16(target_saddr->sa_family);
    unlock_user(target_saddr, target_addr, 0);
B
bellard 已提交
410 411
}

412
static inline void host_to_target_sockaddr(target_ulong target_addr,
B
bellard 已提交
413 414 415
                                           struct sockaddr *addr,
                                           socklen_t len)
{
416 417 418 419 420 421
    struct target_sockaddr *target_saddr;

    target_saddr = lock_user(target_addr, len, 0);
    memcpy(target_saddr, addr, len);
    target_saddr->sa_family = tswap16(addr->sa_family);
    unlock_user(target_saddr, target_addr, len);
B
bellard 已提交
422 423
}

424
/* ??? Should this also swap msgh->name?  */
B
bellard 已提交
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
static inline void target_to_host_cmsg(struct msghdr *msgh,
                                       struct target_msghdr *target_msgh)
{
    struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
    struct target_cmsghdr *target_cmsg = TARGET_CMSG_FIRSTHDR(target_msgh);
    socklen_t space = 0;

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

        int len = tswapl(target_cmsg->cmsg_len) 
                  - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));

        space += CMSG_SPACE(len);
        if (space > msgh->msg_controllen) {
            space -= CMSG_SPACE(len);
B
bellard 已提交
442
            gemu_log("Host cmsg overflow\n");
B
bellard 已提交
443 444 445 446 447 448 449
            break;
        }

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

450
        if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
B
bellard 已提交
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
            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);
    }

    msgh->msg_controllen = space;
}

469
/* ??? Should this also swap msgh->name?  */
B
bellard 已提交
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
static inline void host_to_target_cmsg(struct target_msghdr *target_msgh,
                                       struct msghdr *msgh)
{
    struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
    struct target_cmsghdr *target_cmsg = TARGET_CMSG_FIRSTHDR(target_msgh);
    socklen_t space = 0;

    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);
        if (space > tswapl(target_msgh->msg_controllen)) {
            space -= TARGET_CMSG_SPACE(len);
B
bellard 已提交
486
            gemu_log("Target cmsg overflow\n");
B
bellard 已提交
487 488 489 490 491 492 493
            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));

494
        if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
B
bellard 已提交
495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
            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);
    }

    msgh->msg_controllen = tswapl(space);
}

static long do_setsockopt(int sockfd, int level, int optname, 
514
                          target_ulong optval, socklen_t optlen)
B
bellard 已提交
515
{
516 517 518 519
    int val, ret;
            
    switch(level) {
    case SOL_TCP:
B
bellard 已提交
520 521 522
        /* TCP options all take an 'int' value.  */
        if (optlen < sizeof(uint32_t))
            return -EINVAL;
523
        
524
        val = tget32(optval);
525 526 527 528
        ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
        break;
    case SOL_IP:
        switch(optname) {
B
bellard 已提交
529 530
        case IP_TOS:
        case IP_TTL:
531
        case IP_HDRINCL:
B
bellard 已提交
532 533 534 535 536 537 538 539 540 541 542 543
        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:
544 545
            val = 0;
            if (optlen >= sizeof(uint32_t)) {
546
                val = tget32(optval);
547
            } else if (optlen >= 1) {
548
                val = tget8(optval);
549 550 551 552 553 554 555
            }
            ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
            break;
        default:
            goto unimplemented;
        }
        break;
556
    case TARGET_SOL_SOCKET:
557 558
        switch (optname) {
            /* Options with 'int' argument.  */
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594
        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 已提交
595
#ifdef SO_BSDCOMPAT
596 597 598
        case TARGET_SO_BSDCOMPAT:
		optname = SO_BSDCOMPAT;
		break;
B
bellard 已提交
599
#endif
600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
        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;
615 616 617 618
            break;
        default:
            goto unimplemented;
        }
619 620 621 622 623
	if (optlen < sizeof(uint32_t))
	return -EINVAL;

	val = tget32(optval);
	ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
624
        break;
B
bellard 已提交
625
    default:
626 627 628
    unimplemented:
        gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
        ret = -ENOSYS;
B
bellard 已提交
629
    }
630
    return ret;
B
bellard 已提交
631 632 633
}

static long do_getsockopt(int sockfd, int level, int optname, 
634
                          target_ulong optval, target_ulong optlen)
B
bellard 已提交
635
{
636 637 638
    int len, lv, val, ret;

    switch(level) {
639 640
    case TARGET_SOL_SOCKET:
    	level = SOL_SOCKET;
641
	switch (optname) {
642 643 644 645 646
	case TARGET_SO_LINGER:
	case TARGET_SO_RCVTIMEO:
	case TARGET_SO_SNDTIMEO:
	case TARGET_SO_PEERCRED:
	case TARGET_SO_PEERNAME:
647 648 649
	    /* These don't just return a single integer */
	    goto unimplemented;
        default:
B
bellard 已提交
650 651 652 653 654 655
            goto int_case;
        }
        break;
    case SOL_TCP:
        /* TCP options all take an 'int' value.  */
    int_case:
656
        len = tget32(optlen);
B
bellard 已提交
657 658 659 660 661 662 663 664 665
        if (len < 0)
            return -EINVAL;
        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;
666 667 668 669 670
        if (len == 4)
            tput32(optval, val);
        else
            tput8(optval, val);
        tput32(optlen, len);
B
bellard 已提交
671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
        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:
689
            len = tget32(optlen);
690 691 692 693 694 695
            if (len < 0)
                return -EINVAL;
            lv = sizeof(int);
            ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
            if (ret < 0)
                return ret;
B
bellard 已提交
696 697
            if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
                len = 1;
698 699
                tput32(optlen, len);
                tput8(optval, val);
B
bellard 已提交
700 701 702
            } else {
                if (len > sizeof(int))
                    len = sizeof(int);
703 704
                tput32(optlen, len);
                tput32(optval, val);
B
bellard 已提交
705
            }
706
            break;
B
bellard 已提交
707 708
        default:
            goto unimplemented;
709 710 711 712 713 714 715 716 717 718
        }
        break;
    default:
    unimplemented:
        gemu_log("getsockopt level=%d optname=%d not yet supported\n",
                 level, optname);
        ret = -ENOSYS;
        break;
    }
    return ret;
B
bellard 已提交
719 720
}

721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751
static void lock_iovec(struct iovec *vec, target_ulong target_addr,
                       int count, int copy)
{
    struct target_iovec *target_vec;
    target_ulong base;
    int i;

    target_vec = lock_user(target_addr, count * sizeof(struct target_iovec), 1);
    for(i = 0;i < count; i++) {
        base = tswapl(target_vec[i].iov_base);
        vec[i].iov_len = tswapl(target_vec[i].iov_len);
        vec[i].iov_base = lock_user(base, vec[i].iov_len, copy);
    }
    unlock_user (target_vec, target_addr, 0);
}

static void unlock_iovec(struct iovec *vec, target_ulong target_addr,
                         int count, int copy)
{
    struct target_iovec *target_vec;
    target_ulong base;
    int i;

    target_vec = lock_user(target_addr, count * sizeof(struct target_iovec), 1);
    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);
}

752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839
static long do_socket(int domain, int type, int protocol)
{
#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
    return get_errno(socket(domain, type, protocol));
}

static long do_bind(int sockfd, target_ulong target_addr,
                    socklen_t addrlen)
{
    void *addr = alloca(addrlen);
    
    target_to_host_sockaddr(addr, target_addr, addrlen);
    return get_errno(bind(sockfd, addr, addrlen));
}

static long do_connect(int sockfd, target_ulong target_addr,
                    socklen_t addrlen)
{
    void *addr = alloca(addrlen);
    
    target_to_host_sockaddr(addr, target_addr, addrlen);
    return get_errno(connect(sockfd, addr, addrlen));
}

static long do_sendrecvmsg(int fd, target_ulong target_msg,
                           int flags, int send)
{
    long ret;
    struct target_msghdr *msgp;
    struct msghdr msg;
    int count;
    struct iovec *vec;
    target_ulong target_vec;

    lock_user_struct(msgp, target_msg, 1);
    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);
    
    count = tswapl(msgp->msg_iovlen);
    vec = alloca(count * sizeof(struct iovec));
    target_vec = tswapl(msgp->msg_iov);
    lock_iovec(vec, target_vec, count, send);
    msg.msg_iovlen = count;
    msg.msg_iov = vec;
    
    if (send) {
        target_to_host_cmsg(&msg, msgp);
        ret = get_errno(sendmsg(fd, &msg, flags));
    } else {
        ret = get_errno(recvmsg(fd, &msg, flags));
        if (!is_error(ret))
            host_to_target_cmsg(msgp, &msg);
    }
    unlock_iovec(vec, target_vec, count, !send);
    return ret;
}

P
pbrook 已提交
840 841 842 843
static long do_accept(int fd, target_ulong target_addr,
                      target_ulong target_addrlen)
{
    socklen_t addrlen = tget32(target_addrlen);
T
ths 已提交
844
    void *addr = alloca(addrlen);
P
pbrook 已提交
845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946
    long ret;

    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;
}

static long do_getpeername(int fd, target_ulong target_addr,
                           target_ulong target_addrlen)
{
    socklen_t addrlen = tget32(target_addrlen);
    void *addr = alloca(target_addrlen);
    long ret;

    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;
}

static long do_getsockname(int fd, target_ulong target_addr,
                           target_ulong target_addrlen)
{
    socklen_t addrlen = tget32(target_addrlen);
    void *addr = alloca(target_addrlen);
    long ret;

    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;
}

static long do_socketpair(int domain, int type, int protocol,
                          target_ulong target_tab)
{
    int tab[2];
    long ret;

    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;
}

static long do_sendto(int fd, target_ulong msg, size_t len, int flags,
                      target_ulong target_addr, socklen_t addrlen)
{
    void *addr;
    void *host_msg;
    long ret;

    host_msg = lock_user(msg, len, 1);
    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;
}

static long do_recvfrom(int fd, target_ulong msg, size_t len, int flags,
                        target_ulong target_addr, target_ulong target_addrlen)
{
    socklen_t addrlen;
    void *addr;
    void *host_msg;
    long ret;

    host_msg = lock_user(msg, len, 0);
    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;
}

947
static long do_socketcall(int num, target_ulong vptr)
948 949
{
    long ret;
950
    const int n = sizeof(target_ulong);
951 952 953

    switch(num) {
    case SOCKOP_socket:
B
bellard 已提交
954
	{
955 956 957
            int domain = tgetl(vptr);
            int type = tgetl(vptr + n);
            int protocol = tgetl(vptr + 2 * n);
958
            ret = do_socket(domain, type, protocol);
B
bellard 已提交
959
	}
960 961
        break;
    case SOCKOP_bind:
B
bellard 已提交
962
	{
963 964 965
            int sockfd = tgetl(vptr);
            target_ulong target_addr = tgetl(vptr + n);
            socklen_t addrlen = tgetl(vptr + 2 * n);
966
            ret = do_bind(sockfd, target_addr, addrlen);
B
bellard 已提交
967
        }
968 969
        break;
    case SOCKOP_connect:
B
bellard 已提交
970
        {
971 972 973
            int sockfd = tgetl(vptr);
            target_ulong target_addr = tgetl(vptr + n);
            socklen_t addrlen = tgetl(vptr + 2 * n);
974
            ret = do_connect(sockfd, target_addr, addrlen);
B
bellard 已提交
975
        }
976 977
        break;
    case SOCKOP_listen:
B
bellard 已提交
978
        {
979 980
            int sockfd = tgetl(vptr);
            int backlog = tgetl(vptr + n);
B
bellard 已提交
981 982
            ret = get_errno(listen(sockfd, backlog));
        }
983 984 985
        break;
    case SOCKOP_accept:
        {
986 987 988
            int sockfd = tgetl(vptr);
            target_ulong target_addr = tgetl(vptr + n);
            target_ulong target_addrlen = tgetl(vptr + 2 * n);
P
pbrook 已提交
989
            ret = do_accept(sockfd, target_addr, target_addrlen);
990 991 992 993
        }
        break;
    case SOCKOP_getsockname:
        {
994 995 996
            int sockfd = tgetl(vptr);
            target_ulong target_addr = tgetl(vptr + n);
            target_ulong target_addrlen = tgetl(vptr + 2 * n);
P
pbrook 已提交
997
            ret = do_getsockname(sockfd, target_addr, target_addrlen);
998 999 1000 1001
        }
        break;
    case SOCKOP_getpeername:
        {
1002 1003 1004
            int sockfd = tgetl(vptr);
            target_ulong target_addr = tgetl(vptr + n);
            target_ulong target_addrlen = tgetl(vptr + 2 * n);
P
pbrook 已提交
1005
            ret = do_getpeername(sockfd, target_addr, target_addrlen);
1006 1007 1008 1009
        }
        break;
    case SOCKOP_socketpair:
        {
1010 1011 1012
            int domain = tgetl(vptr);
            int type = tgetl(vptr + n);
            int protocol = tgetl(vptr + 2 * n);
P
pbrook 已提交
1013 1014
            target_ulong tab = tgetl(vptr + 3 * n);
            ret = do_socketpair(domain, type, protocol, tab);
1015 1016 1017
        }
        break;
    case SOCKOP_send:
B
bellard 已提交
1018
        {
1019 1020 1021 1022
            int sockfd = tgetl(vptr);
            target_ulong msg = tgetl(vptr + n);
            size_t len = tgetl(vptr + 2 * n);
            int flags = tgetl(vptr + 3 * n);
P
pbrook 已提交
1023
            ret = do_sendto(sockfd, msg, len, flags, 0, 0);
B
bellard 已提交
1024
        }
1025 1026
        break;
    case SOCKOP_recv:
B
bellard 已提交
1027
        {
1028 1029 1030 1031
            int sockfd = tgetl(vptr);
            target_ulong msg = tgetl(vptr + n);
            size_t len = tgetl(vptr + 2 * n);
            int flags = tgetl(vptr + 3 * n);
P
pbrook 已提交
1032
            ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
B
bellard 已提交
1033
        }
1034 1035
        break;
    case SOCKOP_sendto:
B
bellard 已提交
1036
        {
1037 1038 1039 1040
            int sockfd = tgetl(vptr);
            target_ulong msg = tgetl(vptr + n);
            size_t len = tgetl(vptr + 2 * n);
            int flags = tgetl(vptr + 3 * n);
P
pbrook 已提交
1041
            target_ulong addr = tgetl(vptr + 4 * n);
1042
            socklen_t addrlen = tgetl(vptr + 5 * n);
P
pbrook 已提交
1043
            ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
B
bellard 已提交
1044
        }
1045 1046 1047
        break;
    case SOCKOP_recvfrom:
        {
1048 1049 1050 1051
            int sockfd = tgetl(vptr);
            target_ulong msg = tgetl(vptr + n);
            size_t len = tgetl(vptr + 2 * n);
            int flags = tgetl(vptr + 3 * n);
P
pbrook 已提交
1052 1053 1054
            target_ulong addr = tgetl(vptr + 4 * n);
            target_ulong addrlen = tgetl(vptr + 5 * n);
            ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
1055 1056 1057
        }
        break;
    case SOCKOP_shutdown:
B
bellard 已提交
1058
        {
1059 1060
            int sockfd = tgetl(vptr);
            int how = tgetl(vptr + n);
B
bellard 已提交
1061 1062 1063

            ret = get_errno(shutdown(sockfd, how));
        }
1064 1065 1066
        break;
    case SOCKOP_sendmsg:
    case SOCKOP_recvmsg:
B
bellard 已提交
1067 1068
        {
            int fd;
1069
            target_ulong target_msg;
1070
            int flags;
B
bellard 已提交
1071

1072
            fd = tgetl(vptr);
1073
            target_msg = tgetl(vptr + n);
1074
            flags = tgetl(vptr + 2 * n);
1075 1076 1077

            ret = do_sendrecvmsg(fd, target_msg, flags, 
                                 (num == SOCKOP_sendmsg));
B
bellard 已提交
1078 1079
        }
        break;
1080
    case SOCKOP_setsockopt:
B
bellard 已提交
1081
        {
1082 1083 1084 1085 1086
            int sockfd = tgetl(vptr);
            int level = tgetl(vptr + n);
            int optname = tgetl(vptr + 2 * n);
            target_ulong optval = tgetl(vptr + 3 * n);
            socklen_t optlen = tgetl(vptr + 4 * n);
B
bellard 已提交
1087 1088 1089 1090

            ret = do_setsockopt(sockfd, level, optname, optval, optlen);
        }
        break;
1091
    case SOCKOP_getsockopt:
B
bellard 已提交
1092
        {
1093 1094 1095 1096 1097
            int sockfd = tgetl(vptr);
            int level = tgetl(vptr + n);
            int optname = tgetl(vptr + 2 * n);
            target_ulong optval = tgetl(vptr + 3 * n);
            target_ulong poptlen = tgetl(vptr + 4 * n);
B
bellard 已提交
1098

1099
            ret = do_getsockopt(sockfd, level, optname, optval, poptlen);
B
bellard 已提交
1100 1101
        }
        break;
1102 1103 1104 1105 1106 1107 1108 1109
    default:
        gemu_log("Unsupported socketcall: %d\n", num);
        ret = -ENOSYS;
        break;
    }
    return ret;
}

1110 1111 1112 1113 1114 1115 1116
#define N_SHM_REGIONS	32

static struct shm_region {
    uint32_t	start;
    uint32_t	size;
} shm_regions[N_SHM_REGIONS];

1117
/* ??? This only works with linear mappings.  */
1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195
static long do_ipc(long call, long first, long second, long third,
		   long ptr, long fifth)
{
    int version;
    long ret = 0;
    unsigned long raddr;
    struct shmid_ds shm_info;
    int i;

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

    switch (call) {
    case IPCOP_shmat:
	/* SHM_* flags are the same on all linux platforms */
	ret = get_errno((long) shmat(first, (void *) ptr, second));
        if (is_error(ret))
            break;
        raddr = ret;
	/* 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((void *) raddr);
	    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, (uint32_t *)third))
            return -EFAULT;
        ret = 0;
	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;
	    }
	}
	ret = get_errno(shmdt((void *) ptr));
	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:
	gemu_log("Unsupported ipc call: %ld (version %d)\n", call, version);
	ret = -ENOSYS;
	break;
    }
    return ret;
}

1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
/* 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 {
1214 1215
    unsigned int target_cmd;
    unsigned int host_cmd;
1216 1217
    const char *name;
    int access;
B
bellard 已提交
1218
    const argtype arg_type[5];
1219 1220 1221 1222 1223 1224 1225 1226
} IOCTLEntry;

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

#define MAX_STRUCT_SIZE 4096

1227
IOCTLEntry ioctl_entries[] = {
1228 1229 1230 1231 1232 1233
#define IOCTL(cmd, access, types...) \
    { TARGET_ ## cmd, cmd, #cmd, access, { types } },
#include "ioctls.h"
    { 0, 0, },
};

1234
/* ??? Implement proper locking for ioctls.  */
1235 1236 1237 1238 1239 1240
static long do_ioctl(long fd, long cmd, long arg)
{
    const IOCTLEntry *ie;
    const argtype *arg_type;
    long ret;
    uint8_t buf_temp[MAX_STRUCT_SIZE];
1241 1242
    int target_size;
    void *argptr;
1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254

    ie = ioctl_entries;
    for(;;) {
        if (ie->target_cmd == 0) {
            gemu_log("Unsupported ioctl: cmd=0x%04lx\n", cmd);
            return -ENOSYS;
        }
        if (ie->target_cmd == cmd)
            break;
        ie++;
    }
    arg_type = ie->arg_type;
B
bellard 已提交
1255
#if defined(DEBUG)
B
bellard 已提交
1256 1257
    gemu_log("ioctl: cmd=0x%04lx (%s)\n", cmd, ie->name);
#endif
1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269
    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++;
1270
        target_size = thunk_type_size(arg_type, 0);
1271 1272 1273 1274
        switch(ie->access) {
        case IOC_R:
            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
            if (!is_error(ret)) {
1275 1276 1277
                argptr = lock_user(arg, target_size, 0);
                thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
                unlock_user(argptr, arg, target_size);
1278 1279 1280
            }
            break;
        case IOC_W:
1281 1282 1283
            argptr = lock_user(arg, target_size, 1);
            thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
            unlock_user(argptr, arg, 0);
1284 1285 1286 1287
            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
            break;
        default:
        case IOC_RW:
1288 1289 1290
            argptr = lock_user(arg, target_size, 1);
            thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
            unlock_user(argptr, arg, 0);
1291 1292
            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
            if (!is_error(ret)) {
1293 1294 1295
                argptr = lock_user(arg, target_size, 0);
                thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
                unlock_user(argptr, arg, target_size);
1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481
            }
            break;
        }
        break;
    default:
        gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n", cmd, arg_type[0]);
        ret = -ENOSYS;
        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;
    
    host->c_iflag = 
        target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
    host->c_oflag = 
        target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
    host->c_cflag = 
        target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
    host->c_lflag = 
        target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
    host->c_line = target->c_line;
    
    host->c_cc[VINTR] = target->c_cc[TARGET_VINTR]; 
    host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT]; 
    host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];       
    host->c_cc[VKILL] = target->c_cc[TARGET_VKILL]; 
    host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];   
    host->c_cc[VTIME] = target->c_cc[TARGET_VTIME]; 
    host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];   
    host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC]; 
    host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];       
    host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP]; 
    host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP]; 
    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];       
    host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2]; 
}
  
static void host_to_target_termios (void *dst, const void *src)
{
    struct target_termios *target = dst;
    const struct host_termios *host = src;

    target->c_iflag = 
        tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
    target->c_oflag = 
        tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
    target->c_cflag = 
        tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
    target->c_lflag = 
        tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
    target->c_line = host->c_line;
  
    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 已提交
1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493
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 已提交
1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507
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 已提交
1508
#if defined(O_DIRECT)
B
bellard 已提交
1509
	{ TARGET_O_DIRECT,    TARGET_O_DIRECT,    O_DIRECT,    O_DIRECT,    },
B
bellard 已提交
1510
#endif
B
bellard 已提交
1511 1512 1513
	{ 0, 0, 0, 0 }
};

1514
#if defined(TARGET_I386)
B
bellard 已提交
1515 1516 1517 1518

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

1519
static int read_ldt(target_ulong ptr, unsigned long bytecount)
B
bellard 已提交
1520 1521
{
    int size;
1522
    void *p;
B
bellard 已提交
1523 1524 1525 1526 1527 1528

    if (!ldt_table)
        return 0;
    size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
    if (size > bytecount)
        size = bytecount;
1529 1530 1531 1532
    p = lock_user(ptr, size, 0);
    /* ??? Shoudl this by byteswapped?  */
    memcpy(p, ldt_table, size);
    unlock_user(p, ptr, size);
B
bellard 已提交
1533 1534 1535 1536 1537
    return size;
}

/* XXX: add locking support */
static int write_ldt(CPUX86State *env, 
1538
                     target_ulong ptr, unsigned long bytecount, int oldmode)
B
bellard 已提交
1539 1540
{
    struct target_modify_ldt_ldt_s ldt_info;
1541
    struct target_modify_ldt_ldt_s *target_ldt_info;
B
bellard 已提交
1542 1543 1544 1545 1546 1547
    int seg_32bit, contents, read_exec_only, limit_in_pages;
    int seg_not_present, useable;
    uint32_t *lp, entry_1, entry_2;

    if (bytecount != sizeof(ldt_info))
        return -EINVAL;
1548 1549 1550 1551 1552 1553
    lock_user_struct(target_ldt_info, ptr, 1);
    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);
B
bellard 已提交
1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575
    
    if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
        return -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;

    if (contents == 3) {
        if (oldmode)
            return -EINVAL;
        if (seg_not_present == 0)
            return -EINVAL;
    }
    /* allocate the LDT */
    if (!ldt_table) {
        ldt_table = malloc(TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
        if (!ldt_table)
            return -ENOMEM;
        memset(ldt_table, 0, TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
1576
        env->ldt.base = h2g(ldt_table);
B
bellard 已提交
1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608
        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;
        }
    }
    
    entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
        (ldt_info.limit & 0x0ffff);
    entry_2 = (ldt_info.base_addr & 0xff000000) |
        ((ldt_info.base_addr & 0x00ff0000) >> 16) |
        (ldt_info.limit & 0xf0000) |
        ((read_exec_only ^ 1) << 9) |
        (contents << 10) |
        ((seg_not_present ^ 1) << 15) |
        (seg_32bit << 22) |
        (limit_in_pages << 23) |
        0x7000;
    if (!oldmode)
        entry_2 |= (useable << 20);
B
bellard 已提交
1609

B
bellard 已提交
1610 1611 1612 1613 1614 1615 1616 1617 1618
    /* 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 */
1619
int do_modify_ldt(CPUX86State *env, int func, target_ulong ptr, unsigned long bytecount)
B
bellard 已提交
1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635
{
    int ret = -ENOSYS;
    
    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;
    }
    return ret;
}
B
bellard 已提交
1636

1637 1638
#endif /* defined(TARGET_I386) */

B
bellard 已提交
1639 1640 1641 1642 1643 1644
/* 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)
{
1645
    CPUState *env = arg;
B
bellard 已提交
1646 1647 1648 1649 1650
    cpu_loop(env);
    /* never exits */
    return 0;
}

1651
int do_fork(CPUState *env, unsigned int flags, unsigned long newsp)
B
bellard 已提交
1652 1653
{
    int ret;
B
bellard 已提交
1654
    TaskState *ts;
B
bellard 已提交
1655
    uint8_t *new_stack;
1656
    CPUState *new_env;
B
bellard 已提交
1657 1658
    
    if (flags & CLONE_VM) {
B
bellard 已提交
1659 1660 1661 1662 1663 1664 1665
        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 已提交
1666
        /* we create a new CPU instance. */
1667 1668 1669 1670 1671
        new_env = cpu_init();
        memcpy(new_env, env, sizeof(CPUState));
#if defined(TARGET_I386)
        if (!newsp)
            newsp = env->regs[R_ESP];
B
bellard 已提交
1672 1673
        new_env->regs[R_ESP] = newsp;
        new_env->regs[R_EAX] = 0;
1674 1675 1676 1677 1678
#elif defined(TARGET_ARM)
        if (!newsp)
            newsp = env->regs[13];
        new_env->regs[13] = newsp;
        new_env->regs[0] = 0;
1679
#elif defined(TARGET_SPARC)
B
bellard 已提交
1680 1681 1682 1683 1684
        if (!newsp)
            newsp = env->regwptr[22];
        new_env->regwptr[22] = newsp;
        new_env->regwptr[0] = 0;
	/* XXXXX */
1685
        printf ("HELPME: %s:%d\n", __FILE__, __LINE__);
P
pbrook 已提交
1686 1687 1688 1689 1690 1691
#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 已提交
1692 1693
#elif defined(TARGET_MIPS)
        printf ("HELPME: %s:%d\n", __FILE__, __LINE__);
1694 1695 1696 1697 1698 1699 1700 1701 1702
#elif defined(TARGET_PPC)
        if (!newsp)
            newsp = env->gpr[1];
        new_env->gpr[1] = newsp;
        { 
            int i;
            for (i = 7; i < 32; i++)
                new_env->gpr[i] = 0;
        }
B
bellard 已提交
1703 1704 1705 1706 1707
#elif defined(TARGET_SH4)
	if (!newsp)
	  newsp = env->gregs[15];
	new_env->gregs[15] = newsp;
	/* XXXXX */
1708 1709 1710
#else
#error unsupported target CPU
#endif
B
bellard 已提交
1711
        new_env->opaque = ts;
1712
#ifdef __ia64__
B
bellard 已提交
1713
        ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
1714 1715 1716
#else
	ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
#endif
B
bellard 已提交
1717 1718 1719 1720 1721 1722 1723 1724 1725
    } else {
        /* if no CLONE_VM, we consider it is a fork */
        if ((flags & ~CSIGNAL) != 0)
            return -EINVAL;
        ret = fork();
    }
    return ret;
}

1726
static long do_fcntl(int fd, int cmd, target_ulong arg)
B
bellard 已提交
1727 1728
{
    struct flock fl;
1729
    struct target_flock *target_fl;
B
bellard 已提交
1730
    long ret;
1731

B
bellard 已提交
1732 1733 1734 1735
    switch(cmd) {
    case TARGET_F_GETLK:
        ret = fcntl(fd, cmd, &fl);
        if (ret == 0) {
1736
            lock_user_struct(target_fl, arg, 0);
B
bellard 已提交
1737 1738 1739 1740 1741
            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);
1742
            unlock_user_struct(target_fl, arg, 1);
B
bellard 已提交
1743 1744 1745 1746 1747
        }
        break;
        
    case TARGET_F_SETLK:
    case TARGET_F_SETLKW:
1748
        lock_user_struct(target_fl, arg, 1);
B
bellard 已提交
1749 1750 1751 1752 1753
        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);
1754
        unlock_user_struct(target_fl, arg, 0);
B
bellard 已提交
1755 1756 1757 1758 1759 1760 1761 1762 1763 1764
        ret = fcntl(fd, cmd, &fl);
        break;
        
    case TARGET_F_GETLK64:
    case TARGET_F_SETLK64:
    case TARGET_F_SETLKW64:
        ret = -1;
        errno = EINVAL;
        break;

B
bellard 已提交
1765 1766 1767 1768 1769 1770 1771 1772 1773
    case F_GETFL:
        ret = fcntl(fd, cmd, arg);
        ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
        break;

    case F_SETFL:
        ret = fcntl(fd, cmd, target_to_host_bitmask(arg, fcntl_flags_tbl));
        break;

B
bellard 已提交
1774 1775 1776 1777 1778 1779 1780
    default:
        ret = fcntl(fd, cmd, arg);
        break;
    }
    return ret;
}

1781
#ifdef USE_UID16
B
bellard 已提交
1782

1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815
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 已提交
1816

1817 1818
void syscall_init(void)
{
1819 1820 1821 1822
    IOCTLEntry *ie;
    const argtype *arg_type;
    int size;

1823 1824 1825 1826 1827
#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); 
#include "syscall_types.h"
#undef STRUCT
#undef STRUCT_SPECIAL
1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855

    /* 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) {
                fprintf(stderr, "cannot patch size for ioctl 0x%x\n", 
                        ie->target_cmd);
                exit(1);
            }
            arg_type++;
            size = thunk_type_size(arg_type, 0);
            ie->target_cmd = (ie->target_cmd & 
                              ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
                (size << TARGET_IOC_SIZESHIFT);
        }
        /* automatic consistency check if same arch */
#if defined(__i386__) && defined(TARGET_I386)
        if (ie->target_cmd != ie->host_cmd) {
            fprintf(stderr, "ERROR: ioctl: target=0x%x host=0x%x\n", 
                    ie->target_cmd, ie->host_cmd);
        }
#endif
        ie++;
    }
1856
}
B
bellard 已提交
1857

P
pbrook 已提交
1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896
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
}

#ifdef TARGET_NR_truncate64
static inline long target_truncate64(void *cpu_env, const char *arg1,
                                     long arg2, long arg3, long arg4)
{
#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
static inline long target_ftruncate64(void *cpu_env, long arg1, long arg2,
                                      long arg3, long arg4)
{
#ifdef TARGET_ARM
    if (((CPUARMState *)cpu_env)->eabi)
      {
        arg2 = arg3;
        arg3 = arg4;
      }
#endif
    return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
}
#endif

1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918
static inline void target_to_host_timespec(struct timespec *host_ts,
                                           target_ulong target_addr)
{
    struct target_timespec *target_ts;

    lock_user_struct(target_ts, target_addr, 1);
    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);
}

static inline void host_to_target_timespec(target_ulong target_addr,
                                           struct timespec *host_ts)
{
    struct target_timespec *target_ts;

    lock_user_struct(target_ts, target_addr, 0);
    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);
}

B
bellard 已提交
1919
long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, 
1920 1921 1922 1923
                long arg4, long arg5, long arg6)
{
    long ret;
    struct stat st;
B
bellard 已提交
1924
    struct statfs stfs;
1925
    void *p;
1926
    
B
bellard 已提交
1927
#ifdef DEBUG
B
bellard 已提交
1928
    gemu_log("syscall %d", num);
B
bellard 已提交
1929
#endif
1930 1931
    switch(num) {
    case TARGET_NR_exit:
B
bellard 已提交
1932 1933 1934
#ifdef HAVE_GPROF
        _mcleanup();
#endif
1935
        gdb_exit(cpu_env, arg1);
B
bellard 已提交
1936
        /* XXX: should free thread stack and CPU env */
1937 1938 1939 1940
        _exit(arg1);
        ret = 0; /* avoid warning */
        break;
    case TARGET_NR_read:
1941 1942 1943 1944
        page_unprotect_range(arg2, arg3);
        p = lock_user(arg2, arg3, 0);
        ret = get_errno(read(arg1, p, arg3));
        unlock_user(p, arg2, ret);
1945 1946
        break;
    case TARGET_NR_write:
1947 1948 1949
        p = lock_user(arg2, arg3, 1);
        ret = get_errno(write(arg1, p, arg3));
        unlock_user(p, arg2, 0);
1950 1951
        break;
    case TARGET_NR_open:
1952 1953
        p = lock_user_string(arg1);
        ret = get_errno(open(path(p),
B
bellard 已提交
1954 1955
                             target_to_host_bitmask(arg2, fcntl_flags_tbl),
                             arg3));
1956
        unlock_user(p, arg1, 0);
1957 1958 1959 1960 1961
        break;
    case TARGET_NR_close:
        ret = get_errno(close(arg1));
        break;
    case TARGET_NR_brk:
1962
        ret = do_brk(arg1);
1963 1964
        break;
    case TARGET_NR_fork:
B
bellard 已提交
1965
        ret = get_errno(do_fork(cpu_env, SIGCHLD, 0));
1966 1967 1968
        break;
    case TARGET_NR_waitpid:
        {
1969 1970 1971 1972
            int status;
            ret = get_errno(waitpid(arg1, &status, arg3));
            if (!is_error(ret) && arg2)
                tput32(arg2, status);
1973 1974 1975
        }
        break;
    case TARGET_NR_creat:
1976 1977 1978
        p = lock_user_string(arg1);
        ret = get_errno(creat(p, arg2));
        unlock_user(p, arg1, 0);
1979 1980
        break;
    case TARGET_NR_link:
1981 1982 1983 1984 1985 1986 1987 1988
        {
            void * p2;
            p = lock_user_string(arg1);
            p2 = lock_user_string(arg2);
            ret = get_errno(link(p, p2));
            unlock_user(p2, arg2, 0);
            unlock_user(p, arg1, 0);
        }
1989 1990
        break;
    case TARGET_NR_unlink:
1991 1992 1993
        p = lock_user_string(arg1);
        ret = get_errno(unlink(p));
        unlock_user(p, arg1, 0);
1994 1995
        break;
    case TARGET_NR_execve:
B
bellard 已提交
1996 1997
        {
            char **argp, **envp;
B
bellard 已提交
1998
            int argc, envc;
1999 2000 2001 2002
            target_ulong gp;
            target_ulong guest_argp;
            target_ulong guest_envp;
            target_ulong addr;
B
bellard 已提交
2003 2004
            char **q;

B
bellard 已提交
2005
            argc = 0;
2006 2007
            guest_argp = arg2;
            for (gp = guest_argp; tgetl(gp); gp++)
B
bellard 已提交
2008
                argc++;
B
bellard 已提交
2009
            envc = 0;
2010 2011
            guest_envp = arg3;
            for (gp = guest_envp; tgetl(gp); gp++)
B
bellard 已提交
2012 2013
                envc++;

B
bellard 已提交
2014 2015
            argp = alloca((argc + 1) * sizeof(void *));
            envp = alloca((envc + 1) * sizeof(void *));
B
bellard 已提交
2016

2017 2018 2019 2020 2021 2022 2023
            for (gp = guest_argp, q = argp; ;
                  gp += sizeof(target_ulong), q++) {
                addr = tgetl(gp);
                if (!addr)
                    break;
                *q = lock_user_string(addr);
            }
B
bellard 已提交
2024 2025
            *q = NULL;

2026 2027 2028 2029 2030 2031 2032
            for (gp = guest_envp, q = envp; ;
                  gp += sizeof(target_ulong), q++) {
                addr = tgetl(gp);
                if (!addr)
                    break;
                *q = lock_user_string(addr);
            }
B
bellard 已提交
2033
            *q = NULL;
B
bellard 已提交
2034

2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048
            p = lock_user_string(arg1);
            ret = get_errno(execve(p, argp, envp));
            unlock_user(p, arg1, 0);

            for (gp = guest_argp, q = argp; *q;
                  gp += sizeof(target_ulong), q++) {
                addr = tgetl(gp);
                unlock_user(*q, addr, 0);
            }
            for (gp = guest_envp, q = envp; *q;
                  gp += sizeof(target_ulong), q++) {
                addr = tgetl(gp);
                unlock_user(*q, addr, 0);
            }
B
bellard 已提交
2049
        }
2050 2051
        break;
    case TARGET_NR_chdir:
2052 2053 2054
        p = lock_user_string(arg1);
        ret = get_errno(chdir(p));
        unlock_user(p, arg1, 0);
2055
        break;
B
bellard 已提交
2056
#ifdef TARGET_NR_time
2057 2058
    case TARGET_NR_time:
        {
2059 2060 2061 2062
            time_t host_time;
            ret = get_errno(time(&host_time));
            if (!is_error(ret) && arg1)
                tputl(arg1, host_time);
2063 2064
        }
        break;
B
bellard 已提交
2065
#endif
2066
    case TARGET_NR_mknod:
2067 2068 2069
        p = lock_user_string(arg1);
        ret = get_errno(mknod(p, arg2, arg3));
        unlock_user(p, arg1, 0);
2070 2071
        break;
    case TARGET_NR_chmod:
2072 2073 2074
        p = lock_user_string(arg1);
        ret = get_errno(chmod(p, arg2));
        unlock_user(p, arg1, 0);
2075
        break;
2076
#ifdef TARGET_NR_break
2077 2078
    case TARGET_NR_break:
        goto unimplemented;
2079 2080
#endif
#ifdef TARGET_NR_oldstat
2081 2082
    case TARGET_NR_oldstat:
        goto unimplemented;
2083
#endif
2084 2085 2086 2087 2088 2089 2090 2091 2092 2093
    case TARGET_NR_lseek:
        ret = get_errno(lseek(arg1, arg2, arg3));
        break;
    case TARGET_NR_getpid:
        ret = get_errno(getpid());
        break;
    case TARGET_NR_mount:
        /* need to look at the data field */
        goto unimplemented;
    case TARGET_NR_umount:
2094 2095 2096
        p = lock_user_string(arg1);
        ret = get_errno(umount(p));
        unlock_user(p, arg1, 0);
2097 2098 2099
        break;
    case TARGET_NR_stime:
        {
2100 2101 2102
            time_t host_time;
            host_time = tgetl(arg1);
            ret = get_errno(stime(&host_time));
2103 2104 2105 2106 2107 2108 2109
        }
        break;
    case TARGET_NR_ptrace:
        goto unimplemented;
    case TARGET_NR_alarm:
        ret = alarm(arg1);
        break;
2110
#ifdef TARGET_NR_oldfstat
2111 2112
    case TARGET_NR_oldfstat:
        goto unimplemented;
2113
#endif
2114 2115 2116 2117
    case TARGET_NR_pause:
        ret = get_errno(pause());
        break;
    case TARGET_NR_utime:
2118
        {
2119 2120 2121 2122 2123 2124 2125 2126
            struct utimbuf tbuf, *host_tbuf;
            struct target_utimbuf *target_tbuf;
            if (arg2) {
                lock_user_struct(target_tbuf, arg2, 1);
                tbuf.actime = tswapl(target_tbuf->actime);
                tbuf.modtime = tswapl(target_tbuf->modtime);
                unlock_user_struct(target_tbuf, arg2, 0);
                host_tbuf = &tbuf;
B
bellard 已提交
2127
            } else {
2128
                host_tbuf = NULL;
B
bellard 已提交
2129
            }
2130 2131 2132
            p = lock_user_string(arg1);
            ret = get_errno(utime(p, host_tbuf));
            unlock_user(p, arg1, 0);
2133 2134
        }
        break;
B
bellard 已提交
2135 2136 2137
    case TARGET_NR_utimes:
        {
            struct timeval *tvp, tv[2];
2138 2139 2140 2141
            if (arg2) {
                target_to_host_timeval(&tv[0], arg2);
                target_to_host_timeval(&tv[1],
                    arg2 + sizeof (struct target_timeval));
B
bellard 已提交
2142 2143 2144 2145
                tvp = tv;
            } else {
                tvp = NULL;
            }
2146 2147 2148
            p = lock_user_string(arg1);
            ret = get_errno(utimes(p, tvp));
            unlock_user(p, arg1, 0);
B
bellard 已提交
2149 2150
        }
        break;
2151
#ifdef TARGET_NR_stty
2152 2153
    case TARGET_NR_stty:
        goto unimplemented;
2154 2155
#endif
#ifdef TARGET_NR_gtty
2156 2157
    case TARGET_NR_gtty:
        goto unimplemented;
2158
#endif
2159
    case TARGET_NR_access:
2160 2161 2162
        p = lock_user_string(arg1);
        ret = get_errno(access(p, arg2));
        unlock_user(p, arg1, 0);
2163 2164 2165 2166
        break;
    case TARGET_NR_nice:
        ret = get_errno(nice(arg1));
        break;
2167
#ifdef TARGET_NR_ftime
2168 2169
    case TARGET_NR_ftime:
        goto unimplemented;
2170
#endif
2171
    case TARGET_NR_sync:
B
bellard 已提交
2172 2173
        sync();
        ret = 0;
2174 2175 2176 2177 2178
        break;
    case TARGET_NR_kill:
        ret = get_errno(kill(arg1, arg2));
        break;
    case TARGET_NR_rename:
2179 2180 2181 2182 2183 2184 2185 2186
        {
            void *p2;
            p = lock_user_string(arg1);
            p2 = lock_user_string(arg2);
            ret = get_errno(rename(p, p2));
            unlock_user(p2, arg2, 0);
            unlock_user(p, arg1, 0);
        }
2187 2188
        break;
    case TARGET_NR_mkdir:
2189 2190 2191
        p = lock_user_string(arg1);
        ret = get_errno(mkdir(p, arg2));
        unlock_user(p, arg1, 0);
2192 2193
        break;
    case TARGET_NR_rmdir:
2194 2195 2196
        p = lock_user_string(arg1);
        ret = get_errno(rmdir(p));
        unlock_user(p, arg1, 0);
2197 2198 2199 2200 2201 2202
        break;
    case TARGET_NR_dup:
        ret = get_errno(dup(arg1));
        break;
    case TARGET_NR_pipe:
        {
2203 2204
            int host_pipe[2];
            ret = get_errno(pipe(host_pipe));
2205
            if (!is_error(ret)) {
2206 2207
                tput32(arg1, host_pipe[0]);
                tput32(arg1 + 4, host_pipe[1]);
2208 2209 2210 2211
            }
        }
        break;
    case TARGET_NR_times:
B
bellard 已提交
2212
        {
2213
            struct target_tms *tmsp;
B
bellard 已提交
2214 2215
            struct tms tms;
            ret = get_errno(times(&tms));
2216 2217
            if (arg1) {
                tmsp = lock_user(arg1, sizeof(struct target_tms), 0);
B
bellard 已提交
2218 2219 2220 2221
                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 已提交
2222
            }
B
bellard 已提交
2223 2224
            if (!is_error(ret))
                ret = host_to_target_clock_t(ret);
B
bellard 已提交
2225 2226
        }
        break;
2227
#ifdef TARGET_NR_prof
2228 2229
    case TARGET_NR_prof:
        goto unimplemented;
2230
#endif
2231 2232
    case TARGET_NR_signal:
        goto unimplemented;
2233

2234
    case TARGET_NR_acct:
2235 2236 2237 2238
        p = lock_user_string(arg1);
        ret = get_errno(acct(path(p)));
        unlock_user(p, arg1, 0);
        break;
2239
    case TARGET_NR_umount2:
2240 2241 2242
        p = lock_user_string(arg1);
        ret = get_errno(umount2(p, arg2));
        unlock_user(p, arg1, 0);
2243
        break;
2244
#ifdef TARGET_NR_lock
2245 2246
    case TARGET_NR_lock:
        goto unimplemented;
2247
#endif
2248 2249 2250 2251
    case TARGET_NR_ioctl:
        ret = do_ioctl(arg1, arg2, arg3);
        break;
    case TARGET_NR_fcntl:
B
bellard 已提交
2252
        ret = get_errno(do_fcntl(arg1, arg2, arg3));
2253
        break;
2254
#ifdef TARGET_NR_mpx
2255 2256
    case TARGET_NR_mpx:
        goto unimplemented;
2257
#endif
2258 2259 2260
    case TARGET_NR_setpgid:
        ret = get_errno(setpgid(arg1, arg2));
        break;
2261
#ifdef TARGET_NR_ulimit
2262 2263
    case TARGET_NR_ulimit:
        goto unimplemented;
2264 2265
#endif
#ifdef TARGET_NR_oldolduname
2266 2267
    case TARGET_NR_oldolduname:
        goto unimplemented;
2268
#endif
2269 2270 2271 2272
    case TARGET_NR_umask:
        ret = get_errno(umask(arg1));
        break;
    case TARGET_NR_chroot:
2273 2274 2275
        p = lock_user_string(arg1);
        ret = get_errno(chroot(p));
        unlock_user(p, arg1, 0);
2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292
        break;
    case TARGET_NR_ustat:
        goto unimplemented;
    case TARGET_NR_dup2:
        ret = get_errno(dup2(arg1, arg2));
        break;
    case TARGET_NR_getppid:
        ret = get_errno(getppid());
        break;
    case TARGET_NR_getpgrp:
        ret = get_errno(getpgrp());
        break;
    case TARGET_NR_setsid:
        ret = get_errno(setsid());
        break;
    case TARGET_NR_sigaction:
        {
2293
	#if !defined(TARGET_MIPS)
2294
            struct target_old_sigaction *old_act;
B
bellard 已提交
2295
            struct target_sigaction act, oact, *pact;
2296 2297
            if (arg2) {
                lock_user_struct(old_act, arg2, 1);
B
bellard 已提交
2298 2299 2300 2301
                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;
2302
                unlock_user_struct(old_act, arg2, 0);
B
bellard 已提交
2303 2304 2305 2306 2307
                pact = &act;
            } else {
                pact = NULL;
            }
            ret = get_errno(do_sigaction(arg1, pact, &oact));
2308 2309 2310 2311 2312 2313 2314
            if (!is_error(ret) && arg3) {
                lock_user_struct(old_act, arg3, 0);
                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 已提交
2315
            }
2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342
	#else
	    struct target_sigaction act, oact, *pact, *old_act;

	    if (arg2) {
		lock_user_struct(old_act, arg2, 1);
		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) {
		lock_user_struct(old_act, arg3, 0);
		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);
	    }
	#endif
2343 2344
        }
        break;
B
bellard 已提交
2345
    case TARGET_NR_rt_sigaction:
2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363
        {
            struct target_sigaction *act;
            struct target_sigaction *oact;

            if (arg2)
                lock_user_struct(act, arg2, 1);
            else
                act = NULL;
            if (arg3)
                lock_user_struct(oact, arg3, 0);
            else
                oact = NULL;
            ret = get_errno(do_sigaction(arg1, act, oact));
            if (arg2)
                unlock_user_struct(act, arg2, 0);
            if (arg3)
                unlock_user_struct(oact, arg3, 1);
        }
B
bellard 已提交
2364
        break;
2365
    case TARGET_NR_sgetmask:
B
bellard 已提交
2366 2367 2368 2369 2370 2371 2372 2373
        {
            sigset_t cur_set;
            target_ulong target_set;
            sigprocmask(0, NULL, &cur_set);
            host_to_target_old_sigset(&target_set, &cur_set);
            ret = target_set;
        }
        break;
2374
    case TARGET_NR_ssetmask:
B
bellard 已提交
2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390
        {
            sigset_t set, oset, cur_set;
            target_ulong target_set = arg1;
            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;
    case TARGET_NR_sigprocmask:
        {
            int how = arg1;
            sigset_t set, oldset, *set_ptr;
            
2391
            if (arg2) {
B
bellard 已提交
2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405
                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:
                    ret = -EINVAL;
                    goto fail;
                }
2406 2407 2408
                p = lock_user(arg2, sizeof(target_sigset_t), 1);
                target_to_host_old_sigset(&set, p);
                unlock_user(p, arg2, 0);
B
bellard 已提交
2409 2410 2411 2412 2413 2414
                set_ptr = &set;
            } else {
                how = 0;
                set_ptr = NULL;
            }
            ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
2415 2416 2417 2418
            if (!is_error(ret) && arg3) {
                p = lock_user(arg3, sizeof(target_sigset_t), 0);
                host_to_target_old_sigset(p, &oldset);
                unlock_user(p, arg3, sizeof(target_sigset_t));
B
bellard 已提交
2419 2420 2421 2422 2423 2424 2425 2426
            }
        }
        break;
    case TARGET_NR_rt_sigprocmask:
        {
            int how = arg1;
            sigset_t set, oldset, *set_ptr;
            
2427
            if (arg2) {
B
bellard 已提交
2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441
                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:
                    ret = -EINVAL;
                    goto fail;
                }
2442 2443 2444
                p = lock_user(arg2, sizeof(target_sigset_t), 1);
                target_to_host_sigset(&set, p);
                unlock_user(p, arg2, 0);
B
bellard 已提交
2445 2446 2447 2448 2449 2450
                set_ptr = &set;
            } else {
                how = 0;
                set_ptr = NULL;
            }
            ret = get_errno(sigprocmask(how, set_ptr, &oldset));
2451 2452 2453 2454
            if (!is_error(ret) && arg3) {
                p = lock_user(arg3, sizeof(target_sigset_t), 0);
                host_to_target_sigset(p, &oldset);
                unlock_user(p, arg3, sizeof(target_sigset_t));
B
bellard 已提交
2455 2456 2457 2458 2459 2460 2461 2462
            }
        }
        break;
    case TARGET_NR_sigpending:
        {
            sigset_t set;
            ret = get_errno(sigpending(&set));
            if (!is_error(ret)) {
2463 2464 2465
                p = lock_user(arg1, sizeof(target_sigset_t), 0);
                host_to_target_old_sigset(p, &set);
                unlock_user(p, arg1, sizeof(target_sigset_t));
B
bellard 已提交
2466 2467 2468 2469 2470 2471 2472 2473
            }
        }
        break;
    case TARGET_NR_rt_sigpending:
        {
            sigset_t set;
            ret = get_errno(sigpending(&set));
            if (!is_error(ret)) {
2474 2475 2476
                p = lock_user(arg1, sizeof(target_sigset_t), 0);
                host_to_target_sigset(p, &set);
                unlock_user(p, arg1, sizeof(target_sigset_t));
B
bellard 已提交
2477 2478 2479 2480 2481 2482
            }
        }
        break;
    case TARGET_NR_sigsuspend:
        {
            sigset_t set;
2483 2484 2485
            p = lock_user(arg1, sizeof(target_sigset_t), 1);
            target_to_host_old_sigset(&set, p);
            unlock_user(p, arg1, 0);
B
bellard 已提交
2486 2487 2488 2489 2490 2491
            ret = get_errno(sigsuspend(&set));
        }
        break;
    case TARGET_NR_rt_sigsuspend:
        {
            sigset_t set;
2492 2493 2494
            p = lock_user(arg1, sizeof(target_sigset_t), 1);
            target_to_host_sigset(&set, p);
            unlock_user(p, arg1, 0);
B
bellard 已提交
2495 2496 2497 2498 2499 2500 2501 2502 2503
            ret = get_errno(sigsuspend(&set));
        }
        break;
    case TARGET_NR_rt_sigtimedwait:
        {
            sigset_t set;
            struct timespec uts, *puts;
            siginfo_t uinfo;
            
2504 2505 2506 2507
            p = lock_user(arg1, sizeof(target_sigset_t), 1);
            target_to_host_sigset(&set, p);
            unlock_user(p, arg1, 0);
            if (arg3) {
B
bellard 已提交
2508
                puts = &uts;
2509
                target_to_host_timespec(puts, arg3);
B
bellard 已提交
2510 2511 2512 2513
            } else {
                puts = NULL;
            }
            ret = get_errno(sigtimedwait(&set, &uinfo, puts));
2514 2515 2516 2517
            if (!is_error(ret) && arg2) {
                p = lock_user(arg2, sizeof(target_sigset_t), 0);
                host_to_target_siginfo(p, &uinfo);
                unlock_user(p, arg2, sizeof(target_sigset_t));
B
bellard 已提交
2518 2519 2520 2521 2522 2523
            }
        }
        break;
    case TARGET_NR_rt_sigqueueinfo:
        {
            siginfo_t uinfo;
2524 2525 2526
            p = lock_user(arg3, sizeof(target_sigset_t), 1);
            target_to_host_siginfo(&uinfo, p);
            unlock_user(p, arg1, 0);
B
bellard 已提交
2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537
            ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
        }
        break;
    case TARGET_NR_sigreturn:
        /* NOTE: ret is eax, so not transcoding must be done */
        ret = do_sigreturn(cpu_env);
        break;
    case TARGET_NR_rt_sigreturn:
        /* NOTE: ret is eax, so not transcoding must be done */
        ret = do_rt_sigreturn(cpu_env);
        break;
2538
    case TARGET_NR_sethostname:
2539 2540 2541
        p = lock_user_string(arg1);
        ret = get_errno(sethostname(p, arg2));
        unlock_user(p, arg1, 0);
2542 2543
        break;
    case TARGET_NR_setrlimit:
B
bellard 已提交
2544 2545 2546
        {
            /* XXX: convert resource ? */
            int resource = arg1;
2547
            struct target_rlimit *target_rlim;
B
bellard 已提交
2548
            struct rlimit rlim;
2549
            lock_user_struct(target_rlim, arg2, 1);
B
bellard 已提交
2550 2551
            rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
            rlim.rlim_max = tswapl(target_rlim->rlim_max);
2552
            unlock_user_struct(target_rlim, arg2, 0);
B
bellard 已提交
2553 2554 2555
            ret = get_errno(setrlimit(resource, &rlim));
        }
        break;
2556
    case TARGET_NR_getrlimit:
B
bellard 已提交
2557 2558 2559
        {
            /* XXX: convert resource ? */
            int resource = arg1;
2560
            struct target_rlimit *target_rlim;
B
bellard 已提交
2561 2562 2563 2564
            struct rlimit rlim;
            
            ret = get_errno(getrlimit(resource, &rlim));
            if (!is_error(ret)) {
2565 2566 2567 2568
                lock_user_struct(target_rlim, arg2, 0);
                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 已提交
2569 2570 2571
            }
        }
        break;
2572
    case TARGET_NR_getrusage:
B
bellard 已提交
2573 2574 2575 2576
        {
            struct rusage rusage;
            ret = get_errno(getrusage(arg1, &rusage));
            if (!is_error(ret)) {
2577
                host_to_target_rusage(arg2, &rusage);
B
bellard 已提交
2578 2579 2580
            }
        }
        break;
2581 2582 2583 2584 2585
    case TARGET_NR_gettimeofday:
        {
            struct timeval tv;
            ret = get_errno(gettimeofday(&tv, NULL));
            if (!is_error(ret)) {
2586
                host_to_target_timeval(arg1, &tv);
2587 2588 2589 2590 2591 2592
            }
        }
        break;
    case TARGET_NR_settimeofday:
        {
            struct timeval tv;
2593
            target_to_host_timeval(&tv, arg1);
2594 2595 2596
            ret = get_errno(settimeofday(&tv, NULL));
        }
        break;
B
bellard 已提交
2597
#ifdef TARGET_NR_select
2598
    case TARGET_NR_select:
B
bellard 已提交
2599
        {
2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611
            struct target_sel_arg_struct *sel;
            target_ulong inp, outp, exp, tvp;
            long nsel;

            lock_user_struct(sel, arg1, 1);
            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 已提交
2612 2613
        }
        break;
B
bellard 已提交
2614
#endif
2615
    case TARGET_NR_symlink:
2616 2617 2618 2619 2620 2621 2622 2623
        {
            void *p2;
            p = lock_user_string(arg1);
            p2 = lock_user_string(arg2);
            ret = get_errno(symlink(p, p2));
            unlock_user(p2, arg2, 0);
            unlock_user(p, arg1, 0);
        }
2624
        break;
2625
#ifdef TARGET_NR_oldlstat
2626 2627
    case TARGET_NR_oldlstat:
        goto unimplemented;
2628
#endif
2629
    case TARGET_NR_readlink:
2630 2631 2632 2633 2634 2635 2636 2637
        {
            void *p2;
            p = lock_user_string(arg1);
            p2 = lock_user(arg2, arg3, 0);
            ret = get_errno(readlink(path(p), p2, arg3));
            unlock_user(p2, arg2, ret);
            unlock_user(p, arg1, 0);
        }
2638 2639 2640 2641
        break;
    case TARGET_NR_uselib:
        goto unimplemented;
    case TARGET_NR_swapon:
2642 2643 2644
        p = lock_user_string(arg1);
        ret = get_errno(swapon(p, arg2));
        unlock_user(p, arg1, 0);
2645 2646 2647 2648 2649 2650
        break;
    case TARGET_NR_reboot:
        goto unimplemented;
    case TARGET_NR_readdir:
        goto unimplemented;
    case TARGET_NR_mmap:
P
pbrook 已提交
2651
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_M68K)
2652
        {
2653 2654 2655 2656 2657 2658 2659 2660 2661 2662
            target_ulong *v;
            target_ulong v1, v2, v3, v4, v5, v6;
            v = lock_user(arg1, 6 * sizeof(target_ulong), 1);
            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);
B
bellard 已提交
2663 2664 2665
            ret = get_errno(target_mmap(v1, v2, v3, 
                                        target_to_host_bitmask(v4, mmap_flags_tbl),
                                        v5, v6));
2666 2667
        }
#else
B
bellard 已提交
2668 2669 2670 2671
        ret = get_errno(target_mmap(arg1, arg2, arg3, 
                                    target_to_host_bitmask(arg4, mmap_flags_tbl), 
                                    arg5,
                                    arg6));
2672
#endif
B
bellard 已提交
2673
        break;
B
bellard 已提交
2674
#ifdef TARGET_NR_mmap2
B
bellard 已提交
2675
    case TARGET_NR_mmap2:
T
ths 已提交
2676
#if defined(TARGET_SPARC) || defined(TARGET_MIPS)
B
bellard 已提交
2677 2678 2679 2680
#define MMAP_SHIFT 12
#else
#define MMAP_SHIFT TARGET_PAGE_BITS
#endif
B
bellard 已提交
2681 2682 2683
        ret = get_errno(target_mmap(arg1, arg2, arg3, 
                                    target_to_host_bitmask(arg4, mmap_flags_tbl), 
                                    arg5,
B
bellard 已提交
2684
                                    arg6 << MMAP_SHIFT));
2685
        break;
B
bellard 已提交
2686
#endif
2687
    case TARGET_NR_munmap:
B
bellard 已提交
2688
        ret = get_errno(target_munmap(arg1, arg2));
2689
        break;
B
bellard 已提交
2690
    case TARGET_NR_mprotect:
B
bellard 已提交
2691
        ret = get_errno(target_mprotect(arg1, arg2, arg3));
B
bellard 已提交
2692 2693
        break;
    case TARGET_NR_mremap:
B
bellard 已提交
2694
        ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
B
bellard 已提交
2695
        break;
2696
        /* ??? msync/mlock/munlock are broken for softmmu.  */
B
bellard 已提交
2697
    case TARGET_NR_msync:
2698
        ret = get_errno(msync(g2h(arg1), arg2, arg3));
B
bellard 已提交
2699 2700
        break;
    case TARGET_NR_mlock:
2701
        ret = get_errno(mlock(g2h(arg1), arg2));
B
bellard 已提交
2702 2703
        break;
    case TARGET_NR_munlock:
2704
        ret = get_errno(munlock(g2h(arg1), arg2));
B
bellard 已提交
2705 2706 2707 2708 2709 2710 2711
        break;
    case TARGET_NR_mlockall:
        ret = get_errno(mlockall(arg1));
        break;
    case TARGET_NR_munlockall:
        ret = get_errno(munlockall());
        break;
2712
    case TARGET_NR_truncate:
2713 2714 2715
        p = lock_user_string(arg1);
        ret = get_errno(truncate(p, arg2));
        unlock_user(p, arg1, 0);
2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728
        break;
    case TARGET_NR_ftruncate:
        ret = get_errno(ftruncate(arg1, arg2));
        break;
    case TARGET_NR_fchmod:
        ret = get_errno(fchmod(arg1, arg2));
        break;
    case TARGET_NR_getpriority:
        ret = get_errno(getpriority(arg1, arg2));
        break;
    case TARGET_NR_setpriority:
        ret = get_errno(setpriority(arg1, arg2, arg3));
        break;
2729
#ifdef TARGET_NR_profil
2730 2731
    case TARGET_NR_profil:
        goto unimplemented;
2732
#endif
2733
    case TARGET_NR_statfs:
2734 2735 2736
        p = lock_user_string(arg1);
        ret = get_errno(statfs(path(p), &stfs));
        unlock_user(p, arg1, 0);
2737 2738
    convert_statfs:
        if (!is_error(ret)) {
2739
            struct target_statfs *target_stfs;
B
bellard 已提交
2740
            
2741 2742
            lock_user_struct(target_stfs, arg2, 0);
            /* ??? put_user is probably wrong.  */
B
bellard 已提交
2743 2744 2745 2746 2747 2748 2749 2750 2751
            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);
            put_user(stfs.f_namelen, &target_stfs->f_namelen);
2752
            unlock_user_struct(target_stfs, arg2, 1);
2753 2754 2755
        }
        break;
    case TARGET_NR_fstatfs:
B
bellard 已提交
2756
        ret = get_errno(fstatfs(arg1, &stfs));
2757
        goto convert_statfs;
B
bellard 已提交
2758 2759
#ifdef TARGET_NR_statfs64
    case TARGET_NR_statfs64:
2760 2761 2762
        p = lock_user_string(arg1);
        ret = get_errno(statfs(path(p), &stfs));
        unlock_user(p, arg1, 0);
B
bellard 已提交
2763 2764
    convert_statfs64:
        if (!is_error(ret)) {
2765 2766 2767 2768
            struct target_statfs64 *target_stfs;
            
            lock_user_struct(target_stfs, arg3, 0);
            /* ??? put_user is probably wrong.  */
B
bellard 已提交
2769 2770 2771 2772 2773 2774 2775 2776 2777
            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);
            put_user(stfs.f_namelen, &target_stfs->f_namelen);
2778
            unlock_user_struct(target_stfs, arg3, 0);
B
bellard 已提交
2779 2780 2781 2782 2783 2784
        }
        break;
    case TARGET_NR_fstatfs64:
        ret = get_errno(fstatfs(arg1, &stfs));
        goto convert_statfs64;
#endif
2785
#ifdef TARGET_NR_ioperm
2786 2787
    case TARGET_NR_ioperm:
        goto unimplemented;
2788
#endif
2789
    case TARGET_NR_socketcall:
2790
        ret = do_socketcall(arg1, arg2);
2791
        break;
2792 2793 2794

#ifdef TARGET_NR_accept
    case TARGET_NR_accept:
P
pbrook 已提交
2795
        ret = do_accept(arg1, arg2, arg3);
2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809
        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 已提交
2810
        ret = do_getpeername(arg1, arg2, arg3);
2811 2812 2813 2814
        break;
#endif
#ifdef TARGET_NR_getsockname
    case TARGET_NR_getsockname:
P
pbrook 已提交
2815
        ret = do_getsockname(arg1, arg2, arg3);
2816 2817 2818 2819 2820 2821 2822 2823 2824
        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 已提交
2825
        ret = get_errno(listen(arg1, arg2));
2826 2827 2828 2829
        break;
#endif
#ifdef TARGET_NR_recv
    case TARGET_NR_recv:
P
pbrook 已提交
2830
        ret = do_recvfrom(arg1, arg1, arg3, arg4, 0, 0);
2831 2832 2833 2834
        break;
#endif
#ifdef TARGET_NR_recvfrom
    case TARGET_NR_recvfrom:
P
pbrook 已提交
2835
        ret = do_recvfrom(arg1, arg1, arg3, arg4, arg5, arg6);
2836 2837 2838 2839 2840 2841 2842 2843 2844
        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 已提交
2845
        ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
2846 2847 2848 2849 2850 2851 2852 2853 2854
        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 已提交
2855
        ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
2856 2857 2858 2859
        break;
#endif
#ifdef TARGET_NR_shutdown
    case TARGET_NR_shutdown:
P
pbrook 已提交
2860
        ret = get_errno(shutdown(arg1, arg2));
2861 2862 2863 2864 2865 2866 2867 2868 2869
        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 已提交
2870
        ret = do_socketpair(arg1, arg2, arg3, arg4);
2871 2872 2873 2874 2875 2876 2877 2878
        break;
#endif
#ifdef TARGET_NR_setsockopt
    case TARGET_NR_setsockopt:
        ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
        break;
#endif
        
2879 2880 2881
    case TARGET_NR_syslog:
        goto unimplemented;
    case TARGET_NR_setitimer:
B
bellard 已提交
2882 2883 2884
        {
            struct itimerval value, ovalue, *pvalue;

2885
            if (arg2) {
B
bellard 已提交
2886 2887
                pvalue = &value;
                target_to_host_timeval(&pvalue->it_interval, 
2888
                                       arg2);
B
bellard 已提交
2889
                target_to_host_timeval(&pvalue->it_value, 
2890
                                       arg2 + sizeof(struct target_timeval));
B
bellard 已提交
2891 2892 2893 2894
            } else {
                pvalue = NULL;
            }
            ret = get_errno(setitimer(arg1, pvalue, &ovalue));
2895 2896
            if (!is_error(ret) && arg3) {
                host_to_target_timeval(arg3,
B
bellard 已提交
2897
                                       &ovalue.it_interval);
2898
                host_to_target_timeval(arg3 + sizeof(struct target_timeval),
B
bellard 已提交
2899 2900 2901 2902
                                       &ovalue.it_value);
            }
        }
        break;
2903
    case TARGET_NR_getitimer:
B
bellard 已提交
2904 2905 2906 2907
        {
            struct itimerval value;
            
            ret = get_errno(getitimer(arg1, &value));
2908 2909
            if (!is_error(ret) && arg2) {
                host_to_target_timeval(arg2,
B
bellard 已提交
2910
                                       &value.it_interval);
2911
                host_to_target_timeval(arg2 + sizeof(struct target_timeval),
B
bellard 已提交
2912 2913 2914 2915
                                       &value.it_value);
            }
        }
        break;
2916
    case TARGET_NR_stat:
2917 2918 2919
        p = lock_user_string(arg1);
        ret = get_errno(stat(path(p), &st));
        unlock_user(p, arg1, 0);
2920 2921
        goto do_stat;
    case TARGET_NR_lstat:
2922 2923 2924
        p = lock_user_string(arg1);
        ret = get_errno(lstat(path(p), &st));
        unlock_user(p, arg1, 0);
2925 2926 2927 2928 2929 2930
        goto do_stat;
    case TARGET_NR_fstat:
        {
            ret = get_errno(fstat(arg1, &st));
        do_stat:
            if (!is_error(ret)) {
2931 2932 2933
                struct target_stat *target_st;
                
                lock_user_struct(target_st, arg2, 0);
2934 2935
                target_st->st_dev = tswap16(st.st_dev);
                target_st->st_ino = tswapl(st.st_ino);
2936
#if defined(TARGET_PPC) || defined(TARGET_MIPS)
2937 2938 2939 2940
                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);
#else
2941
                target_st->st_mode = tswap16(st.st_mode);
2942 2943
                target_st->st_uid = tswap16(st.st_uid);
                target_st->st_gid = tswap16(st.st_gid);
2944 2945
#endif
                target_st->st_nlink = tswap16(st.st_nlink);
2946 2947 2948 2949
                target_st->st_rdev = tswap16(st.st_rdev);
                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 已提交
2950 2951 2952
                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);
2953
                unlock_user_struct(target_st, arg2, 1);
2954 2955 2956
            }
        }
        break;
2957
#ifdef TARGET_NR_olduname
2958 2959
    case TARGET_NR_olduname:
        goto unimplemented;
2960 2961
#endif
#ifdef TARGET_NR_iopl
2962 2963
    case TARGET_NR_iopl:
        goto unimplemented;
2964
#endif
2965 2966 2967
    case TARGET_NR_vhangup:
        ret = get_errno(vhangup());
        break;
2968
#ifdef TARGET_NR_idle
2969 2970
    case TARGET_NR_idle:
        goto unimplemented;
B
bellard 已提交
2971 2972 2973 2974 2975
#endif
#ifdef TARGET_NR_syscall
    case TARGET_NR_syscall:
    	ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
    	break;
2976
#endif
2977 2978 2979
    case TARGET_NR_wait4:
        {
            int status;
2980
            target_long status_ptr = arg2;
2981
            struct rusage rusage, *rusage_ptr;
2982
            target_ulong target_rusage = arg4;
2983 2984 2985 2986 2987 2988 2989
            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)
2990
                    tputl(status_ptr, status);
2991
                if (target_rusage) {
B
bellard 已提交
2992
                    host_to_target_rusage(target_rusage, &rusage);
2993 2994 2995 2996 2997
                }
            }
        }
        break;
    case TARGET_NR_swapoff:
2998 2999 3000
        p = lock_user_string(arg1);
        ret = get_errno(swapoff(p));
        unlock_user(p, arg1, 0);
3001 3002
        break;
    case TARGET_NR_sysinfo:
B
bellard 已提交
3003
        {
3004
            struct target_sysinfo *target_value;
B
bellard 已提交
3005 3006
            struct sysinfo value;
            ret = get_errno(sysinfo(&value));
3007
            if (!is_error(ret) && arg1)
B
bellard 已提交
3008
            {
3009 3010
                /* ??? __put_user is probably wrong.  */
                lock_user_struct(target_value, arg1, 0);
B
bellard 已提交
3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024
                __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);
3025
                unlock_user_struct(target_value, arg1, 1);
B
bellard 已提交
3026 3027 3028
            }
        }
        break;
3029
    case TARGET_NR_ipc:
3030 3031
	ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
	break;
3032 3033 3034 3035
    case TARGET_NR_fsync:
        ret = get_errno(fsync(arg1));
        break;
    case TARGET_NR_clone:
B
bellard 已提交
3036 3037
        ret = get_errno(do_fork(cpu_env, arg1, arg2));
        break;
3038 3039 3040
#ifdef __NR_exit_group
        /* new thread calls */
    case TARGET_NR_exit_group:
3041
        gdb_exit(cpu_env, arg1);
3042 3043 3044
        ret = get_errno(exit_group(arg1));
        break;
#endif
3045
    case TARGET_NR_setdomainname:
3046 3047 3048
        p = lock_user_string(arg1);
        ret = get_errno(setdomainname(p, arg2));
        unlock_user(p, arg1, 0);
3049 3050 3051
        break;
    case TARGET_NR_uname:
        /* no need to transcode because we use the linux syscall */
B
bellard 已提交
3052 3053 3054
        {
            struct new_utsname * buf;
    
3055
            lock_user_struct(buf, arg1, 0);
B
bellard 已提交
3056 3057 3058 3059 3060
            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);
3061 3062 3063
                /* Allow the user to override the reported release.  */
                if (qemu_uname_release && *qemu_uname_release)
                  strcpy (buf->release, qemu_uname_release);
B
bellard 已提交
3064
            }
3065
            unlock_user_struct(buf, arg1, 1);
B
bellard 已提交
3066
        }
3067
        break;
B
bellard 已提交
3068
#ifdef TARGET_I386
3069
    case TARGET_NR_modify_ldt:
3070
        ret = get_errno(do_modify_ldt(cpu_env, arg1, arg2, arg3));
B
bellard 已提交
3071 3072 3073 3074
        break;
    case TARGET_NR_vm86old:
        goto unimplemented;
    case TARGET_NR_vm86:
3075
        ret = do_vm86(cpu_env, arg1, arg2);
B
bellard 已提交
3076 3077
        break;
#endif
3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097
    case TARGET_NR_adjtimex:
        goto unimplemented;
    case TARGET_NR_create_module:
    case TARGET_NR_init_module:
    case TARGET_NR_delete_module:
    case TARGET_NR_get_kernel_syms:
        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;
    case TARGET_NR_bdflush:
        goto unimplemented;
    case TARGET_NR_sysfs:
        goto unimplemented;
    case TARGET_NR_personality:
B
bellard 已提交
3098
        ret = get_errno(personality(arg1));
3099 3100 3101 3102 3103
        break;
    case TARGET_NR_afs_syscall:
        goto unimplemented;
    case TARGET_NR__llseek:
        {
B
bellard 已提交
3104 3105
#if defined (__x86_64__)
            ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
3106
            tput64(arg4, ret);
B
bellard 已提交
3107
#else
3108 3109
            int64_t res;
            ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
3110
            tput64(arg4, res);
B
bellard 已提交
3111
#endif
3112 3113 3114 3115
        }
        break;
    case TARGET_NR_getdents:
#if TARGET_LONG_SIZE != 4
3116
        goto unimplemented;
B
bellard 已提交
3117
#warning not supported
B
bellard 已提交
3118 3119
#elif TARGET_LONG_SIZE == 4 && HOST_LONG_SIZE == 8
        {
3120
            struct target_dirent *target_dirp;
B
bellard 已提交
3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137
            struct dirent *dirp;
            long count = arg3;

	    dirp = malloc(count);
	    if (!dirp)
                return -ENOMEM;
            
            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;
3138
                target_dirp = lock_user(arg2, count, 0);
B
bellard 已提交
3139 3140 3141 3142 3143 3144 3145 3146 3147 3148
		tde = target_dirp;
                while (len > 0) {
                    reclen = de->d_reclen;
		    treclen = reclen - (2 * (sizeof(long) - sizeof(target_long)));
                    tde->d_reclen = tswap16(treclen);
                    tde->d_ino = tswapl(de->d_ino);
                    tde->d_off = tswapl(de->d_off);
		    tnamelen = treclen - (2 * sizeof(target_long) + 2);
		    if (tnamelen > 256)
                        tnamelen = 256;
B
bellard 已提交
3149
                    /* XXX: may not be correct */
B
bellard 已提交
3150 3151 3152 3153 3154 3155 3156 3157
		    strncpy(tde->d_name, de->d_name, tnamelen);
                    de = (struct dirent *)((char *)de + reclen);
                    len -= reclen;
                    tde = (struct dirent *)((char *)tde + treclen);
		    count1 += treclen;
                }
		ret = count1;
            }
3158
            unlock_user(target_dirp, arg2, ret);
B
bellard 已提交
3159 3160 3161
	    free(dirp);
        }
#else
3162
        {
3163
            struct dirent *dirp;
3164
            long count = arg3;
B
bellard 已提交
3165

3166
            dirp = lock_user(arg2, count, 0);
B
bellard 已提交
3167
            ret = get_errno(sys_getdents(arg1, dirp, count));
3168 3169 3170 3171 3172 3173
            if (!is_error(ret)) {
                struct dirent *de;
                int len = ret;
                int reclen;
                de = dirp;
                while (len > 0) {
B
bellard 已提交
3174
                    reclen = de->d_reclen;
3175 3176
                    if (reclen > len)
                        break;
B
bellard 已提交
3177
                    de->d_reclen = tswap16(reclen);
3178 3179 3180 3181 3182 3183
                    tswapls(&de->d_ino);
                    tswapls(&de->d_off);
                    de = (struct dirent *)((char *)de + reclen);
                    len -= reclen;
                }
            }
3184
            unlock_user(dirp, arg2, ret);
3185
        }
B
bellard 已提交
3186
#endif
3187
        break;
3188
#ifdef TARGET_NR_getdents64
B
bellard 已提交
3189 3190
    case TARGET_NR_getdents64:
        {
3191
            struct dirent64 *dirp;
B
bellard 已提交
3192
            long count = arg3;
3193
            dirp = lock_user(arg2, count, 0);
B
bellard 已提交
3194 3195 3196 3197 3198 3199 3200
            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 已提交
3201
                    reclen = de->d_reclen;
B
bellard 已提交
3202 3203
                    if (reclen > len)
                        break;
B
bellard 已提交
3204
                    de->d_reclen = tswap16(reclen);
B
bellard 已提交
3205 3206 3207 3208 3209 3210
                    tswap64s(&de->d_ino);
                    tswap64s(&de->d_off);
                    de = (struct dirent64 *)((char *)de + reclen);
                    len -= reclen;
                }
            }
3211
            unlock_user(dirp, arg2, ret);
B
bellard 已提交
3212 3213
        }
        break;
3214
#endif /* TARGET_NR_getdents64 */
3215
    case TARGET_NR__newselect:
3216
        ret = do_select(arg1, arg2, arg3, arg4, arg5);
3217
        break;
B
bellard 已提交
3218 3219
    case TARGET_NR_poll:
        {
3220
            struct target_pollfd *target_pfd;
B
bellard 已提交
3221 3222 3223
            unsigned int nfds = arg2;
            int timeout = arg3;
            struct pollfd *pfd;
B
bellard 已提交
3224
            unsigned int i;
B
bellard 已提交
3225

3226
            target_pfd = lock_user(arg1, sizeof(struct target_pollfd) * nfds, 1);
B
bellard 已提交
3227 3228
            pfd = alloca(sizeof(struct pollfd) * nfds);
            for(i = 0; i < nfds; i++) {
B
bellard 已提交
3229 3230
                pfd[i].fd = tswap32(target_pfd[i].fd);
                pfd[i].events = tswap16(target_pfd[i].events);
B
bellard 已提交
3231 3232 3233 3234
            }
            ret = get_errno(poll(pfd, nfds, timeout));
            if (!is_error(ret)) {
                for(i = 0; i < nfds; i++) {
B
bellard 已提交
3235
                    target_pfd[i].revents = tswap16(pfd[i].revents);
B
bellard 已提交
3236
                }
3237 3238
                ret += nfds * (sizeof(struct target_pollfd)
                               - sizeof(struct pollfd));
B
bellard 已提交
3239
            }
3240
            unlock_user(target_pfd, arg1, ret);
B
bellard 已提交
3241 3242
        }
        break;
3243
    case TARGET_NR_flock:
B
bellard 已提交
3244 3245 3246
        /* NOTE: the flock constant seems to be the same for every
           Linux platform */
        ret = get_errno(flock(arg1, arg2));
3247 3248 3249 3250 3251 3252 3253
        break;
    case TARGET_NR_readv:
        {
            int count = arg3;
            struct iovec *vec;

            vec = alloca(count * sizeof(struct iovec));
3254
            lock_iovec(vec, arg2, count, 0);
3255
            ret = get_errno(readv(arg1, vec, count));
3256
            unlock_iovec(vec, arg2, count, 1);
3257 3258 3259 3260 3261 3262 3263 3264
        }
        break;
    case TARGET_NR_writev:
        {
            int count = arg3;
            struct iovec *vec;

            vec = alloca(count * sizeof(struct iovec));
3265
            lock_iovec(vec, arg2, count, 1);
3266
            ret = get_errno(writev(arg1, vec, count));
3267
            unlock_iovec(vec, arg2, count, 0);
3268 3269 3270 3271 3272 3273
        }
        break;
    case TARGET_NR_getsid:
        ret = get_errno(getsid(arg1));
        break;
    case TARGET_NR_fdatasync:
B
bellard 已提交
3274 3275
        ret = get_errno(fdatasync(arg1));
        break;
3276
    case TARGET_NR__sysctl:
B
bellard 已提交
3277 3278 3279
        /* We don't implement this, but ENODIR is always a safe
           return value. */
        return -ENOTDIR;
3280
    case TARGET_NR_sched_setparam:
B
bellard 已提交
3281
        {
3282
            struct sched_param *target_schp;
B
bellard 已提交
3283
            struct sched_param schp;
3284 3285

            lock_user_struct(target_schp, arg2, 1);
B
bellard 已提交
3286
            schp.sched_priority = tswap32(target_schp->sched_priority);
3287
            unlock_user_struct(target_schp, arg2, 0);
B
bellard 已提交
3288 3289 3290
            ret = get_errno(sched_setparam(arg1, &schp));
        }
        break;
3291
    case TARGET_NR_sched_getparam:
B
bellard 已提交
3292
        {
3293
            struct sched_param *target_schp;
B
bellard 已提交
3294 3295 3296
            struct sched_param schp;
            ret = get_errno(sched_getparam(arg1, &schp));
            if (!is_error(ret)) {
3297
                lock_user_struct(target_schp, arg2, 0);
B
bellard 已提交
3298
                target_schp->sched_priority = tswap32(schp.sched_priority);
3299
                unlock_user_struct(target_schp, arg2, 1);
B
bellard 已提交
3300 3301 3302
            }
        }
        break;
3303
    case TARGET_NR_sched_setscheduler:
B
bellard 已提交
3304
        {
3305
            struct sched_param *target_schp;
B
bellard 已提交
3306
            struct sched_param schp;
3307
            lock_user_struct(target_schp, arg3, 1);
B
bellard 已提交
3308
            schp.sched_priority = tswap32(target_schp->sched_priority);
3309
            unlock_user_struct(target_schp, arg3, 0);
B
bellard 已提交
3310 3311 3312
            ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
        }
        break;
3313
    case TARGET_NR_sched_getscheduler:
B
bellard 已提交
3314 3315
        ret = get_errno(sched_getscheduler(arg1));
        break;
3316 3317 3318 3319
    case TARGET_NR_sched_yield:
        ret = get_errno(sched_yield());
        break;
    case TARGET_NR_sched_get_priority_max:
B
bellard 已提交
3320 3321
        ret = get_errno(sched_get_priority_max(arg1));
        break;
3322
    case TARGET_NR_sched_get_priority_min:
B
bellard 已提交
3323 3324
        ret = get_errno(sched_get_priority_min(arg1));
        break;
3325
    case TARGET_NR_sched_rr_get_interval:
B
bellard 已提交
3326 3327 3328 3329
        {
            struct timespec ts;
            ret = get_errno(sched_rr_get_interval(arg1, &ts));
            if (!is_error(ret)) {
3330
                host_to_target_timespec(arg2, &ts);
B
bellard 已提交
3331 3332 3333
            }
        }
        break;
3334
    case TARGET_NR_nanosleep:
B
bellard 已提交
3335 3336
        {
            struct timespec req, rem;
3337
            target_to_host_timespec(&req, arg1);
B
bellard 已提交
3338
            ret = get_errno(nanosleep(&req, &rem));
3339 3340
            if (is_error(ret) && arg2) {
                host_to_target_timespec(arg2, &rem);
B
bellard 已提交
3341 3342 3343
            }
        }
        break;
3344
    case TARGET_NR_query_module:
B
bellard 已提交
3345
        goto unimplemented;
3346
    case TARGET_NR_nfsservctl:
B
bellard 已提交
3347
        goto unimplemented;
3348
    case TARGET_NR_prctl:
B
bellard 已提交
3349
        goto unimplemented;
3350
#ifdef TARGET_NR_pread
3351
    case TARGET_NR_pread:
3352 3353 3354 3355
        page_unprotect_range(arg2, arg3);
        p = lock_user(arg2, arg3, 0);
        ret = get_errno(pread(arg1, p, arg3, arg4));
        unlock_user(p, arg2, ret);
3356
        break;
3357
    case TARGET_NR_pwrite:
3358 3359 3360
        p = lock_user(arg2, arg3, 1);
        ret = get_errno(pwrite(arg1, p, arg3, arg4));
        unlock_user(p, arg2, 0);
3361
        break;
3362
#endif
3363
    case TARGET_NR_getcwd:
3364 3365 3366
        p = lock_user(arg1, arg2, 0);
        ret = get_errno(sys_getcwd1(p, arg2));
        unlock_user(p, arg1, ret);
3367 3368
        break;
    case TARGET_NR_capget:
B
bellard 已提交
3369
        goto unimplemented;
3370
    case TARGET_NR_capset:
B
bellard 已提交
3371
        goto unimplemented;
3372
    case TARGET_NR_sigaltstack:
B
bellard 已提交
3373
        goto unimplemented;
3374
    case TARGET_NR_sendfile:
B
bellard 已提交
3375
        goto unimplemented;
3376
#ifdef TARGET_NR_getpmsg
3377
    case TARGET_NR_getpmsg:
B
bellard 已提交
3378
        goto unimplemented;
3379 3380
#endif
#ifdef TARGET_NR_putpmsg
3381
    case TARGET_NR_putpmsg:
B
bellard 已提交
3382
        goto unimplemented;
3383
#endif
B
bellard 已提交
3384
#ifdef TARGET_NR_vfork
3385
    case TARGET_NR_vfork:
B
bellard 已提交
3386
        ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0));
3387
        break;
B
bellard 已提交
3388
#endif
3389
#ifdef TARGET_NR_ugetrlimit
3390
    case TARGET_NR_ugetrlimit:
B
bellard 已提交
3391 3392 3393 3394
    {
	struct rlimit rlim;
	ret = get_errno(getrlimit(arg1, &rlim));
	if (!is_error(ret)) {
3395 3396
	    struct target_rlimit *target_rlim;
            lock_user_struct(target_rlim, arg2, 0);
B
bellard 已提交
3397 3398
	    target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
	    target_rlim->rlim_max = tswapl(rlim.rlim_max);
3399
            unlock_user_struct(target_rlim, arg2, 1);
B
bellard 已提交
3400 3401 3402
	}
	break;
    }
3403
#endif
B
bellard 已提交
3404
#ifdef TARGET_NR_truncate64
3405
    case TARGET_NR_truncate64:
3406 3407 3408
        p = lock_user_string(arg1);
	ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
        unlock_user(p, arg1, 0);
B
bellard 已提交
3409
	break;
B
bellard 已提交
3410 3411
#endif
#ifdef TARGET_NR_ftruncate64
3412
    case TARGET_NR_ftruncate64:
P
pbrook 已提交
3413
	ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
B
bellard 已提交
3414
	break;
B
bellard 已提交
3415 3416
#endif
#ifdef TARGET_NR_stat64
3417
    case TARGET_NR_stat64:
3418 3419 3420
        p = lock_user_string(arg1);
        ret = get_errno(stat(path(p), &st));
        unlock_user(p, arg1, 0);
B
bellard 已提交
3421
        goto do_stat64;
B
bellard 已提交
3422 3423
#endif
#ifdef TARGET_NR_lstat64
3424
    case TARGET_NR_lstat64:
3425 3426 3427
        p = lock_user_string(arg1);
        ret = get_errno(lstat(path(p), &st));
        unlock_user(p, arg1, 0);
B
bellard 已提交
3428
        goto do_stat64;
B
bellard 已提交
3429 3430
#endif
#ifdef TARGET_NR_fstat64
3431
    case TARGET_NR_fstat64:
B
bellard 已提交
3432 3433 3434 3435
        {
            ret = get_errno(fstat(arg1, &st));
        do_stat64:
            if (!is_error(ret)) {
P
pbrook 已提交
3436 3437
#ifdef TARGET_ARM
                if (((CPUARMState *)cpu_env)->eabi) {
3438 3439
                    struct target_eabi_stat64 *target_st;
                    lock_user_struct(target_st, arg2, 1);
P
pbrook 已提交
3440
                    memset(target_st, 0, sizeof(struct target_eabi_stat64));
3441
                    /* put_user is probably wrong.  */
P
pbrook 已提交
3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458
                    put_user(st.st_dev, &target_st->st_dev);
                    put_user(st.st_ino, &target_st->st_ino);
#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
                    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);
                    /* XXX: better use of kernel struct */
                    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);
3459
                    unlock_user_struct(target_st, arg2, 0);
P
pbrook 已提交
3460 3461 3462
                } else
#endif
                {
3463 3464
                    struct target_stat64 *target_st;
                    lock_user_struct(target_st, arg2, 1);
P
pbrook 已提交
3465
                    memset(target_st, 0, sizeof(struct target_stat64));
3466
                    /* ??? put_user is probably wrong.  */
P
pbrook 已提交
3467 3468
                    put_user(st.st_dev, &target_st->st_dev);
                    put_user(st.st_ino, &target_st->st_ino);
3469
#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
P
pbrook 已提交
3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483
                    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);
                    /* XXX: better use of kernel struct */
                    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);
3484
                    unlock_user_struct(target_st, arg2, 0);
P
pbrook 已提交
3485
                }
B
bellard 已提交
3486 3487 3488
            }
        }
        break;
B
bellard 已提交
3489
#endif
3490 3491
#ifdef USE_UID16
    case TARGET_NR_lchown:
3492 3493 3494
        p = lock_user_string(arg1);
        ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
        unlock_user(p, arg1, 0);
3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516
        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;
3517
            uint16_t *target_grouplist;
3518 3519 3520 3521 3522 3523
            gid_t *grouplist;
            int i;

            grouplist = alloca(gidsetsize * sizeof(gid_t));
            ret = get_errno(getgroups(gidsetsize, grouplist));
            if (!is_error(ret)) {
3524
                target_grouplist = lock_user(arg2, gidsetsize * 2, 0);
3525 3526
                for(i = 0;i < gidsetsize; i++)
                    target_grouplist[i] = tswap16(grouplist[i]);
3527
                unlock_user(target_grouplist, arg2, gidsetsize * 2);
3528 3529 3530 3531 3532 3533
            }
        }
        break;
    case TARGET_NR_setgroups:
        {
            int gidsetsize = arg1;
3534
            uint16_t *target_grouplist;
3535 3536 3537 3538
            gid_t *grouplist;
            int i;

            grouplist = alloca(gidsetsize * sizeof(gid_t));
3539
            target_grouplist = lock_user(arg2, gidsetsize * 2, 1);
3540 3541
            for(i = 0;i < gidsetsize; i++)
                grouplist[i] = tswap16(target_grouplist[i]);
3542
            unlock_user(target_grouplist, arg2, 0);
3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558
            ret = get_errno(setgroups(gidsetsize, grouplist));
        }
        break;
    case TARGET_NR_fchown:
        ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
        break;
#ifdef TARGET_NR_setresuid
    case TARGET_NR_setresuid:
        ret = get_errno(setresuid(low2highuid(arg1), 
                                  low2highuid(arg2), 
                                  low2highuid(arg3)));
        break;
#endif
#ifdef TARGET_NR_getresuid
    case TARGET_NR_getresuid:
        {
3559
            uid_t ruid, euid, suid;
3560 3561
            ret = get_errno(getresuid(&ruid, &euid, &suid));
            if (!is_error(ret)) {
3562 3563 3564
                tput16(arg1, tswap16(high2lowuid(ruid)));
                tput16(arg2, tswap16(high2lowuid(euid)));
                tput16(arg3, tswap16(high2lowuid(suid)));
3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578
            }
        }
        break;
#endif
#ifdef TARGET_NR_getresgid
    case TARGET_NR_setresgid:
        ret = get_errno(setresgid(low2highgid(arg1), 
                                  low2highgid(arg2), 
                                  low2highgid(arg3)));
        break;
#endif
#ifdef TARGET_NR_getresgid
    case TARGET_NR_getresgid:
        {
3579
            gid_t rgid, egid, sgid;
3580 3581
            ret = get_errno(getresgid(&rgid, &egid, &sgid));
            if (!is_error(ret)) {
3582 3583 3584
                tput16(arg1, tswap16(high2lowgid(rgid)));
                tput16(arg2, tswap16(high2lowgid(egid)));
                tput16(arg3, tswap16(high2lowgid(sgid)));
3585 3586 3587 3588 3589
            }
        }
        break;
#endif
    case TARGET_NR_chown:
3590 3591 3592
        p = lock_user_string(arg1);
        ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
        unlock_user(p, arg1, 0);
3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607
        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 已提交
3608
#ifdef TARGET_NR_lchown32
3609
    case TARGET_NR_lchown32:
3610 3611 3612
        p = lock_user_string(arg1);
        ret = get_errno(lchown(p, arg2, arg3));
        unlock_user(p, arg1, 0);
B
bellard 已提交
3613
        break;
B
bellard 已提交
3614 3615
#endif
#ifdef TARGET_NR_getuid32
3616
    case TARGET_NR_getuid32:
B
bellard 已提交
3617 3618
        ret = get_errno(getuid());
        break;
B
bellard 已提交
3619 3620
#endif
#ifdef TARGET_NR_getgid32
3621
    case TARGET_NR_getgid32:
B
bellard 已提交
3622 3623
        ret = get_errno(getgid());
        break;
B
bellard 已提交
3624 3625
#endif
#ifdef TARGET_NR_geteuid32
3626
    case TARGET_NR_geteuid32:
B
bellard 已提交
3627 3628
        ret = get_errno(geteuid());
        break;
B
bellard 已提交
3629 3630
#endif
#ifdef TARGET_NR_getegid32
3631
    case TARGET_NR_getegid32:
B
bellard 已提交
3632 3633
        ret = get_errno(getegid());
        break;
B
bellard 已提交
3634 3635
#endif
#ifdef TARGET_NR_setreuid32
3636
    case TARGET_NR_setreuid32:
B
bellard 已提交
3637 3638
        ret = get_errno(setreuid(arg1, arg2));
        break;
B
bellard 已提交
3639 3640
#endif
#ifdef TARGET_NR_setregid32
3641
    case TARGET_NR_setregid32:
B
bellard 已提交
3642 3643
        ret = get_errno(setregid(arg1, arg2));
        break;
B
bellard 已提交
3644 3645
#endif
#ifdef TARGET_NR_getgroups32
3646
    case TARGET_NR_getgroups32:
B
bellard 已提交
3647 3648
        {
            int gidsetsize = arg1;
3649
            uint32_t *target_grouplist;
B
bellard 已提交
3650 3651 3652 3653 3654 3655
            gid_t *grouplist;
            int i;

            grouplist = alloca(gidsetsize * sizeof(gid_t));
            ret = get_errno(getgroups(gidsetsize, grouplist));
            if (!is_error(ret)) {
3656
                target_grouplist = lock_user(arg2, gidsetsize * 4, 0);
B
bellard 已提交
3657
                for(i = 0;i < gidsetsize; i++)
3658 3659
                    target_grouplist[i] = tswap32(grouplist[i]);
                unlock_user(target_grouplist, arg2, gidsetsize * 4);
B
bellard 已提交
3660 3661 3662
            }
        }
        break;
B
bellard 已提交
3663 3664
#endif
#ifdef TARGET_NR_setgroups32
3665
    case TARGET_NR_setgroups32:
B
bellard 已提交
3666 3667
        {
            int gidsetsize = arg1;
3668
            uint32_t *target_grouplist;
B
bellard 已提交
3669 3670 3671 3672
            gid_t *grouplist;
            int i;
            
            grouplist = alloca(gidsetsize * sizeof(gid_t));
3673
            target_grouplist = lock_user(arg2, gidsetsize * 4, 1);
B
bellard 已提交
3674
            for(i = 0;i < gidsetsize; i++)
3675 3676
                grouplist[i] = tswap32(target_grouplist[i]);
            unlock_user(target_grouplist, arg2, 0);
B
bellard 已提交
3677 3678 3679
            ret = get_errno(setgroups(gidsetsize, grouplist));
        }
        break;
B
bellard 已提交
3680 3681
#endif
#ifdef TARGET_NR_fchown32
3682
    case TARGET_NR_fchown32:
B
bellard 已提交
3683 3684
        ret = get_errno(fchown(arg1, arg2, arg3));
        break;
B
bellard 已提交
3685 3686
#endif
#ifdef TARGET_NR_setresuid32
3687
    case TARGET_NR_setresuid32:
B
bellard 已提交
3688 3689
        ret = get_errno(setresuid(arg1, arg2, arg3));
        break;
B
bellard 已提交
3690 3691
#endif
#ifdef TARGET_NR_getresuid32
3692
    case TARGET_NR_getresuid32:
B
bellard 已提交
3693
        {
3694
            uid_t ruid, euid, suid;
B
bellard 已提交
3695 3696
            ret = get_errno(getresuid(&ruid, &euid, &suid));
            if (!is_error(ret)) {
3697 3698 3699
                tput32(arg1, tswap32(ruid));
                tput32(arg2, tswap32(euid));
                tput32(arg3, tswap32(suid));
B
bellard 已提交
3700 3701 3702
            }
        }
        break;
B
bellard 已提交
3703 3704
#endif
#ifdef TARGET_NR_setresgid32
3705
    case TARGET_NR_setresgid32:
B
bellard 已提交
3706 3707
        ret = get_errno(setresgid(arg1, arg2, arg3));
        break;
B
bellard 已提交
3708 3709
#endif
#ifdef TARGET_NR_getresgid32
3710
    case TARGET_NR_getresgid32:
B
bellard 已提交
3711
        {
3712
            gid_t rgid, egid, sgid;
B
bellard 已提交
3713 3714
            ret = get_errno(getresgid(&rgid, &egid, &sgid));
            if (!is_error(ret)) {
3715 3716 3717
                tput32(arg1, tswap32(rgid));
                tput32(arg2, tswap32(egid));
                tput32(arg3, tswap32(sgid));
B
bellard 已提交
3718 3719 3720
            }
        }
        break;
B
bellard 已提交
3721 3722
#endif
#ifdef TARGET_NR_chown32
3723
    case TARGET_NR_chown32:
3724 3725 3726
        p = lock_user_string(arg1);
        ret = get_errno(chown(p, arg2, arg3));
        unlock_user(p, arg1, 0);
B
bellard 已提交
3727
        break;
B
bellard 已提交
3728 3729
#endif
#ifdef TARGET_NR_setuid32
3730
    case TARGET_NR_setuid32:
B
bellard 已提交
3731 3732
        ret = get_errno(setuid(arg1));
        break;
B
bellard 已提交
3733 3734
#endif
#ifdef TARGET_NR_setgid32
3735
    case TARGET_NR_setgid32:
B
bellard 已提交
3736 3737
        ret = get_errno(setgid(arg1));
        break;
B
bellard 已提交
3738 3739
#endif
#ifdef TARGET_NR_setfsuid32
3740
    case TARGET_NR_setfsuid32:
B
bellard 已提交
3741 3742
        ret = get_errno(setfsuid(arg1));
        break;
B
bellard 已提交
3743 3744
#endif
#ifdef TARGET_NR_setfsgid32
3745
    case TARGET_NR_setfsgid32:
B
bellard 已提交
3746 3747
        ret = get_errno(setfsgid(arg1));
        break;
B
bellard 已提交
3748
#endif
3749

3750
    case TARGET_NR_pivot_root:
B
bellard 已提交
3751
        goto unimplemented;
B
bellard 已提交
3752
#ifdef TARGET_NR_mincore
3753
    case TARGET_NR_mincore:
B
bellard 已提交
3754
        goto unimplemented;
B
bellard 已提交
3755 3756
#endif
#ifdef TARGET_NR_madvise
3757
    case TARGET_NR_madvise:
3758 3759 3760 3761 3762 3763
        /* 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 已提交
3764
#endif
B
bellard 已提交
3765
#if TARGET_LONG_BITS == 32
3766
    case TARGET_NR_fcntl64:
B
bellard 已提交
3767 3768
    {
	struct flock64 fl;
3769
	struct target_flock64 *target_fl;
P
pbrook 已提交
3770
#ifdef TARGET_ARM
3771
	struct target_eabi_flock64 *target_efl;
P
pbrook 已提交
3772
#endif
B
bellard 已提交
3773

B
bellard 已提交
3774 3775
        switch(arg2) {
        case F_GETLK64:
B
bellard 已提交
3776 3777
            ret = get_errno(fcntl(arg1, arg2, &fl));
	    if (ret == 0) {
P
pbrook 已提交
3778 3779
#ifdef TARGET_ARM
                if (((CPUARMState *)cpu_env)->eabi) {
3780
                    lock_user_struct(target_efl, arg3, 0);
P
pbrook 已提交
3781 3782 3783 3784 3785
                    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);
3786
                    unlock_user_struct(target_efl, arg3, 1);
P
pbrook 已提交
3787 3788 3789
                } else
#endif
                {
3790
                    lock_user_struct(target_fl, arg3, 0);
P
pbrook 已提交
3791 3792 3793 3794 3795
                    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);
3796
                    unlock_user_struct(target_fl, arg3, 1);
P
pbrook 已提交
3797
                }
B
bellard 已提交
3798 3799 3800
	    }
	    break;

B
bellard 已提交
3801 3802
        case F_SETLK64:
        case F_SETLKW64:
P
pbrook 已提交
3803 3804
#ifdef TARGET_ARM
            if (((CPUARMState *)cpu_env)->eabi) {
3805
                lock_user_struct(target_efl, arg3, 1);
P
pbrook 已提交
3806 3807 3808 3809 3810
                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);
3811
                unlock_user_struct(target_efl, arg3, 0);
P
pbrook 已提交
3812 3813 3814
            } else
#endif
            {
3815
                lock_user_struct(target_fl, arg3, 1);
P
pbrook 已提交
3816 3817 3818 3819 3820
                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);
3821
                unlock_user_struct(target_fl, arg3, 0);
P
pbrook 已提交
3822
            }
B
bellard 已提交
3823 3824
            ret = get_errno(fcntl(arg1, arg2, &fl));
	    break;
B
bellard 已提交
3825
        default:
B
bellard 已提交
3826
            ret = get_errno(do_fcntl(arg1, arg2, arg3));
B
bellard 已提交
3827 3828
            break;
        }
B
bellard 已提交
3829 3830
	break;
    }
B
bellard 已提交
3831
#endif
3832 3833 3834 3835 3836 3837
#ifdef TARGET_NR_cacheflush
    case TARGET_NR_cacheflush:
        /* self-modifying code is handled automatically, so nothing needed */
        ret = 0;
        break;
#endif
3838
#ifdef TARGET_NR_security
3839 3840
    case TARGET_NR_security:
        goto unimplemented;
B
bellard 已提交
3841 3842 3843 3844 3845
#endif
#ifdef TARGET_NR_getpagesize
    case TARGET_NR_getpagesize:
        ret = TARGET_PAGE_SIZE;
        break;
3846
#endif
3847 3848 3849 3850
    case TARGET_NR_gettid:
        ret = get_errno(gettid());
        break;
    case TARGET_NR_readahead:
B
bellard 已提交
3851
        goto unimplemented;
3852
#ifdef TARGET_NR_setxattr
3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864
    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 已提交
3865
        goto unimplemented_nowarn;
3866 3867
#endif
#ifdef TARGET_NR_set_thread_area
B
bellard 已提交
3868 3869 3870
    case TARGET_NR_set_thread_area:
    case TARGET_NR_get_thread_area:
        goto unimplemented_nowarn;
B
bellard 已提交
3871 3872 3873 3874
#endif
#ifdef TARGET_NR_getdomainname
    case TARGET_NR_getdomainname:
        goto unimplemented_nowarn;
3875
#endif
3876 3877
    default:
    unimplemented:
B
bellard 已提交
3878
        gemu_log("qemu: Unsupported syscall: %d\n", num);
B
bellard 已提交
3879
#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_set_thread_area) || defined(TARGET_NR_getdomainname)
B
bellard 已提交
3880
    unimplemented_nowarn:
B
bellard 已提交
3881
#endif
3882 3883 3884 3885
        ret = -ENOSYS;
        break;
    }
 fail:
B
bellard 已提交
3886 3887 3888
#ifdef DEBUG
    gemu_log(" = %ld\n", ret);
#endif
3889 3890 3891
    return ret;
}