Annotation of qemu/linux-user/syscall.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *  Linux syscalls
        !             3:  * 
        !             4:  *  Copyright (c) 2003 Fabrice Bellard
        !             5:  *
        !             6:  *  This program is free software; you can redistribute it and/or modify
        !             7:  *  it under the terms of the GNU General Public License as published by
        !             8:  *  the Free Software Foundation; either version 2 of the License, or
        !             9:  *  (at your option) any later version.
        !            10:  *
        !            11:  *  This program is distributed in the hope that it will be useful,
        !            12:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            14:  *  GNU General Public License for more details.
        !            15:  *
        !            16:  *  You should have received a copy of the GNU General Public License
        !            17:  *  along with this program; if not, write to the Free Software
        !            18:  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        !            19:  */
        !            20: #include <stdlib.h>
        !            21: #include <stdio.h>
        !            22: #include <stdarg.h>
        !            23: #include <string.h>
        !            24: #include <elf.h>
        !            25: #include <endian.h>
        !            26: #include <errno.h>
        !            27: #include <unistd.h>
        !            28: #include <fcntl.h>
        !            29: #include <time.h>
        !            30: #include <sys/types.h>
        !            31: #include <sys/wait.h>
        !            32: #include <sys/time.h>
        !            33: #include <sys/stat.h>
        !            34: #include <sys/mount.h>
        !            35: #include <sys/resource.h>
        !            36: #include <sys/mman.h>
        !            37: #include <sys/swap.h>
        !            38: #include <signal.h>
        !            39: #include <sched.h>
        !            40: #include <sys/socket.h>
        !            41: #include <sys/uio.h>
        !            42: #include <sys/poll.h>
        !            43: #include <sys/times.h>
        !            44: #include <sys/shm.h>
        !            45: #include <utime.h>
        !            46: #include <sys/sysinfo.h>
        !            47: //#include <sys/user.h>
        !            48: #include <netinet/ip.h>
        !            49: #include <netinet/tcp.h>
        !            50: 
        !            51: #define termios host_termios
        !            52: #define winsize host_winsize
        !            53: #define termio host_termio
        !            54: #define sgttyb host_sgttyb /* same as target */
        !            55: #define tchars host_tchars /* same as target */
        !            56: #define ltchars host_ltchars /* same as target */
        !            57: 
        !            58: #include <linux/termios.h>
        !            59: #include <linux/unistd.h>
        !            60: #include <linux/utsname.h>
        !            61: #include <linux/cdrom.h>
        !            62: #include <linux/hdreg.h>
        !            63: #include <linux/soundcard.h>
        !            64: #include <linux/dirent.h>
        !            65: #include <linux/kd.h>
        !            66: 
        !            67: #include "qemu.h"
        !            68: 
        !            69: //#define DEBUG
        !            70: 
        !            71: #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC)
        !            72: /* 16 bit uid wrappers emulation */
        !            73: #define USE_UID16
        !            74: #endif
        !            75: 
        !            76: //#include <linux/msdos_fs.h>
        !            77: #define        VFAT_IOCTL_READDIR_BOTH         _IOR('r', 1, struct dirent [2])
        !            78: #define        VFAT_IOCTL_READDIR_SHORT        _IOR('r', 2, struct dirent [2])
        !            79: 
        !            80: 
        !            81: #if defined(__powerpc__)
        !            82: #undef __syscall_nr
        !            83: #undef __sc_loadargs_0
        !            84: #undef __sc_loadargs_1
        !            85: #undef __sc_loadargs_2
        !            86: #undef __sc_loadargs_3
        !            87: #undef __sc_loadargs_4
        !            88: #undef __sc_loadargs_5
        !            89: #undef __sc_asm_input_0
        !            90: #undef __sc_asm_input_1
        !            91: #undef __sc_asm_input_2
        !            92: #undef __sc_asm_input_3
        !            93: #undef __sc_asm_input_4
        !            94: #undef __sc_asm_input_5
        !            95: #undef _syscall0
        !            96: #undef _syscall1
        !            97: #undef _syscall2
        !            98: #undef _syscall3
        !            99: #undef _syscall4
        !           100: #undef _syscall5
        !           101: 
        !           102: /* need to redefine syscalls as Linux kernel defines are incorrect for
        !           103:    the clobber list */
        !           104: /* On powerpc a system call basically clobbers the same registers like a
        !           105:  * function call, with the exception of LR (which is needed for the
        !           106:  * "sc; bnslr" sequence) and CR (where only CR0.SO is clobbered to signal
        !           107:  * an error return status).
        !           108:  */
        !           109: 
        !           110: #define __syscall_nr(nr, type, name, args...)                          \
        !           111:        unsigned long __sc_ret, __sc_err;                               \
        !           112:        {                                                               \
        !           113:                register unsigned long __sc_0  __asm__ ("r0");          \
        !           114:                register unsigned long __sc_3  __asm__ ("r3");          \
        !           115:                register unsigned long __sc_4  __asm__ ("r4");          \
        !           116:                register unsigned long __sc_5  __asm__ ("r5");          \
        !           117:                register unsigned long __sc_6  __asm__ ("r6");          \
        !           118:                register unsigned long __sc_7  __asm__ ("r7");          \
        !           119:                                                                        \
        !           120:                __sc_loadargs_##nr(name, args);                         \
        !           121:                __asm__ __volatile__                                    \
        !           122:                        ("sc           \n\t"                            \
        !           123:                         "mfcr %0      "                                \
        !           124:                        : "=&r" (__sc_0),                               \
        !           125:                          "=&r" (__sc_3),  "=&r" (__sc_4),              \
        !           126:                          "=&r" (__sc_5),  "=&r" (__sc_6),              \
        !           127:                          "=&r" (__sc_7)                                \
        !           128:                        : __sc_asm_input_##nr                           \
        !           129:                        : "cr0", "ctr", "memory",                       \
        !           130:                          "r8", "r9", "r10","r11", "r12");              \
        !           131:                __sc_ret = __sc_3;                                      \
        !           132:                __sc_err = __sc_0;                                      \
        !           133:        }                                                               \
        !           134:        if (__sc_err & 0x10000000)                                      \
        !           135:        {                                                               \
        !           136:                errno = __sc_ret;                                       \
        !           137:                __sc_ret = -1;                                          \
        !           138:        }                                                               \
        !           139:        return (type) __sc_ret
        !           140: 
        !           141: #define __sc_loadargs_0(name, dummy...)                                        \
        !           142:        __sc_0 = __NR_##name
        !           143: #define __sc_loadargs_1(name, arg1)                                    \
        !           144:        __sc_loadargs_0(name);                                          \
        !           145:        __sc_3 = (unsigned long) (arg1)
        !           146: #define __sc_loadargs_2(name, arg1, arg2)                              \
        !           147:        __sc_loadargs_1(name, arg1);                                    \
        !           148:        __sc_4 = (unsigned long) (arg2)
        !           149: #define __sc_loadargs_3(name, arg1, arg2, arg3)                                \
        !           150:        __sc_loadargs_2(name, arg1, arg2);                              \
        !           151:        __sc_5 = (unsigned long) (arg3)
        !           152: #define __sc_loadargs_4(name, arg1, arg2, arg3, arg4)                  \
        !           153:        __sc_loadargs_3(name, arg1, arg2, arg3);                        \
        !           154:        __sc_6 = (unsigned long) (arg4)
        !           155: #define __sc_loadargs_5(name, arg1, arg2, arg3, arg4, arg5)            \
        !           156:        __sc_loadargs_4(name, arg1, arg2, arg3, arg4);                  \
        !           157:        __sc_7 = (unsigned long) (arg5)
        !           158: 
        !           159: #define __sc_asm_input_0 "0" (__sc_0)
        !           160: #define __sc_asm_input_1 __sc_asm_input_0, "1" (__sc_3)
        !           161: #define __sc_asm_input_2 __sc_asm_input_1, "2" (__sc_4)
        !           162: #define __sc_asm_input_3 __sc_asm_input_2, "3" (__sc_5)
        !           163: #define __sc_asm_input_4 __sc_asm_input_3, "4" (__sc_6)
        !           164: #define __sc_asm_input_5 __sc_asm_input_4, "5" (__sc_7)
        !           165: 
        !           166: #define _syscall0(type,name)                                           \
        !           167: type name(void)                                                                \
        !           168: {                                                                      \
        !           169:        __syscall_nr(0, type, name);                                    \
        !           170: }
        !           171: 
        !           172: #define _syscall1(type,name,type1,arg1)                                        \
        !           173: type name(type1 arg1)                                                  \
        !           174: {                                                                      \
        !           175:        __syscall_nr(1, type, name, arg1);                              \
        !           176: }
        !           177: 
        !           178: #define _syscall2(type,name,type1,arg1,type2,arg2)                     \
        !           179: type name(type1 arg1, type2 arg2)                                      \
        !           180: {                                                                      \
        !           181:        __syscall_nr(2, type, name, arg1, arg2);                        \
        !           182: }
        !           183: 
        !           184: #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)          \
        !           185: type name(type1 arg1, type2 arg2, type3 arg3)                          \
        !           186: {                                                                      \
        !           187:        __syscall_nr(3, type, name, arg1, arg2, arg3);                  \
        !           188: }
        !           189: 
        !           190: #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
        !           191: type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4)              \
        !           192: {                                                                      \
        !           193:        __syscall_nr(4, type, name, arg1, arg2, arg3, arg4);            \
        !           194: }
        !           195: 
        !           196: #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
        !           197: type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)  \
        !           198: {                                                                      \
        !           199:        __syscall_nr(5, type, name, arg1, arg2, arg3, arg4, arg5);      \
        !           200: }
        !           201: #endif
        !           202: 
        !           203: #define __NR_sys_uname __NR_uname
        !           204: #define __NR_sys_getcwd1 __NR_getcwd
        !           205: #define __NR_sys_statfs __NR_statfs
        !           206: #define __NR_sys_fstatfs __NR_fstatfs
        !           207: #define __NR_sys_getdents __NR_getdents
        !           208: #define __NR_sys_getdents64 __NR_getdents64
        !           209: #define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
        !           210: 
        !           211: #if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
        !           212: #define __NR__llseek __NR_lseek
        !           213: #endif
        !           214: 
        !           215: #ifdef __NR_gettid
        !           216: _syscall0(int, gettid)
        !           217: #else
        !           218: static int gettid(void) {
        !           219:     return -ENOSYS;
        !           220: }
        !           221: #endif
        !           222: _syscall1(int,sys_uname,struct new_utsname *,buf)
        !           223: _syscall2(int,sys_getcwd1,char *,buf,size_t,size)
        !           224: _syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count);
        !           225: _syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count);
        !           226: _syscall5(int, _llseek,  uint,  fd, ulong, hi, ulong, lo,
        !           227:           loff_t *, res, uint, wh);
        !           228: _syscall2(int,sys_statfs,const char *,path,struct kernel_statfs *,buf)
        !           229: _syscall2(int,sys_fstatfs,int,fd,struct kernel_statfs *,buf)
        !           230: _syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
        !           231: #ifdef __NR_exit_group
        !           232: _syscall1(int,exit_group,int,error_code)
        !           233: #endif
        !           234: 
        !           235: extern int personality(int);
        !           236: extern int flock(int, int);
        !           237: extern int setfsuid(int);
        !           238: extern int setfsgid(int);
        !           239: extern int setresuid(uid_t, uid_t, uid_t);
        !           240: extern int getresuid(uid_t *, uid_t *, uid_t *);
        !           241: extern int setresgid(gid_t, gid_t, gid_t);
        !           242: extern int getresgid(gid_t *, gid_t *, gid_t *);
        !           243: extern int setgroups(int, gid_t *);
        !           244: 
        !           245: static inline long get_errno(long ret)
        !           246: {
        !           247:     if (ret == -1)
        !           248:         return -errno;
        !           249:     else
        !           250:         return ret;
        !           251: }
        !           252: 
        !           253: static inline int is_error(long ret)
        !           254: {
        !           255:     return (unsigned long)ret >= (unsigned long)(-4096);
        !           256: }
        !           257: 
        !           258: static char *target_brk;
        !           259: static char *target_original_brk;
        !           260: 
        !           261: void target_set_brk(char *new_brk)
        !           262: {
        !           263:     target_brk = new_brk;
        !           264:     target_original_brk = new_brk;
        !           265: }
        !           266: 
        !           267: long do_brk(char *new_brk)
        !           268: {
        !           269:     char *brk_page;
        !           270:     long mapped_addr;
        !           271:     int        new_alloc_size;
        !           272: 
        !           273:     if (!new_brk)
        !           274:         return (long)target_brk;
        !           275:     if (new_brk < target_original_brk)
        !           276:         return -ENOMEM;
        !           277:     
        !           278:     brk_page = (char *)HOST_PAGE_ALIGN((unsigned long)target_brk);
        !           279: 
        !           280:     /* If the new brk is less than this, set it and we're done... */
        !           281:     if (new_brk < brk_page) {
        !           282:        target_brk = new_brk;
        !           283:        return (long)target_brk;
        !           284:     }
        !           285: 
        !           286:     /* We need to allocate more memory after the brk... */
        !           287:     new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
        !           288:     mapped_addr = get_errno(target_mmap((unsigned long)brk_page, new_alloc_size, 
        !           289:                                         PROT_READ|PROT_WRITE,
        !           290:                                         MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
        !           291:     if (is_error(mapped_addr)) {
        !           292:        return mapped_addr;
        !           293:     } else {
        !           294:        target_brk = new_brk;
        !           295:        return (long)target_brk;
        !           296:     }
        !           297: }
        !           298: 
        !           299: static inline fd_set *target_to_host_fds(fd_set *fds, 
        !           300:                                          target_long *target_fds, int n)
        !           301: {
        !           302: #if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN)
        !           303:     return (fd_set *)target_fds;
        !           304: #else
        !           305:     int i, b;
        !           306:     if (target_fds) {
        !           307:         FD_ZERO(fds);
        !           308:         for(i = 0;i < n; i++) {
        !           309:             b = (tswapl(target_fds[i / TARGET_LONG_BITS]) >>
        !           310:                  (i & (TARGET_LONG_BITS - 1))) & 1;
        !           311:             if (b)
        !           312:                 FD_SET(i, fds);
        !           313:         }
        !           314:         return fds;
        !           315:     } else {
        !           316:         return NULL;
        !           317:     }
        !           318: #endif
        !           319: }
        !           320: 
        !           321: static inline void host_to_target_fds(target_long *target_fds, 
        !           322:                                       fd_set *fds, int n)
        !           323: {
        !           324: #if !defined(BSWAP_NEEDED) && !defined(WORDS_BIGENDIAN)
        !           325:     /* nothing to do */
        !           326: #else
        !           327:     int i, nw, j, k;
        !           328:     target_long v;
        !           329: 
        !           330:     if (target_fds) {
        !           331:         nw = (n + TARGET_LONG_BITS - 1) / TARGET_LONG_BITS;
        !           332:         k = 0;
        !           333:         for(i = 0;i < nw; i++) {
        !           334:             v = 0;
        !           335:             for(j = 0; j < TARGET_LONG_BITS; j++) {
        !           336:                 v |= ((FD_ISSET(k, fds) != 0) << j);
        !           337:                 k++;
        !           338:             }
        !           339:             target_fds[i] = tswapl(v);
        !           340:         }
        !           341:     }
        !           342: #endif
        !           343: }
        !           344: 
        !           345: #if defined(__alpha__)
        !           346: #define HOST_HZ 1024
        !           347: #else
        !           348: #define HOST_HZ 100
        !           349: #endif
        !           350: 
        !           351: static inline long host_to_target_clock_t(long ticks)
        !           352: {
        !           353: #if HOST_HZ == TARGET_HZ
        !           354:     return ticks;
        !           355: #else
        !           356:     return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
        !           357: #endif
        !           358: }
        !           359: 
        !           360: static inline void host_to_target_rusage(struct target_rusage *target_rusage, 
        !           361:                                          const struct rusage *rusage)
        !           362: {
        !           363:     target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
        !           364:     target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
        !           365:     target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
        !           366:     target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec);
        !           367:     target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss);
        !           368:     target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss);
        !           369:     target_rusage->ru_idrss = tswapl(rusage->ru_idrss);
        !           370:     target_rusage->ru_isrss = tswapl(rusage->ru_isrss);
        !           371:     target_rusage->ru_minflt = tswapl(rusage->ru_minflt);
        !           372:     target_rusage->ru_majflt = tswapl(rusage->ru_majflt);
        !           373:     target_rusage->ru_nswap = tswapl(rusage->ru_nswap);
        !           374:     target_rusage->ru_inblock = tswapl(rusage->ru_inblock);
        !           375:     target_rusage->ru_oublock = tswapl(rusage->ru_oublock);
        !           376:     target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd);
        !           377:     target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv);
        !           378:     target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals);
        !           379:     target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
        !           380:     target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
        !           381: }
        !           382: 
        !           383: static inline void target_to_host_timeval(struct timeval *tv, 
        !           384:                                           const struct target_timeval *target_tv)
        !           385: {
        !           386:     tv->tv_sec = tswapl(target_tv->tv_sec);
        !           387:     tv->tv_usec = tswapl(target_tv->tv_usec);
        !           388: }
        !           389: 
        !           390: static inline void host_to_target_timeval(struct target_timeval *target_tv, 
        !           391:                                           const struct timeval *tv)
        !           392: {
        !           393:     target_tv->tv_sec = tswapl(tv->tv_sec);
        !           394:     target_tv->tv_usec = tswapl(tv->tv_usec);
        !           395: }
        !           396: 
        !           397: 
        !           398: static long do_select(long n, 
        !           399:                       target_long *target_rfds, target_long *target_wfds, 
        !           400:                       target_long *target_efds, struct target_timeval *target_tv)
        !           401: {
        !           402:     fd_set rfds, wfds, efds;
        !           403:     fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
        !           404:     struct timeval tv, *tv_ptr;
        !           405:     long ret;
        !           406: 
        !           407:     rfds_ptr = target_to_host_fds(&rfds, target_rfds, n);
        !           408:     wfds_ptr = target_to_host_fds(&wfds, target_wfds, n);
        !           409:     efds_ptr = target_to_host_fds(&efds, target_efds, n);
        !           410:             
        !           411:     if (target_tv) {
        !           412:         target_to_host_timeval(&tv, target_tv);
        !           413:         tv_ptr = &tv;
        !           414:     } else {
        !           415:         tv_ptr = NULL;
        !           416:     }
        !           417:     ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
        !           418:     if (!is_error(ret)) {
        !           419:         host_to_target_fds(target_rfds, rfds_ptr, n);
        !           420:         host_to_target_fds(target_wfds, wfds_ptr, n);
        !           421:         host_to_target_fds(target_efds, efds_ptr, n);
        !           422: 
        !           423:         if (target_tv) {
        !           424:             host_to_target_timeval(target_tv, &tv);
        !           425:         }
        !           426:     }
        !           427:     return ret;
        !           428: }
        !           429: 
        !           430: static inline void target_to_host_sockaddr(struct sockaddr *addr,
        !           431:                                            struct target_sockaddr *target_addr,
        !           432:                                            socklen_t len)
        !           433: {
        !           434:     memcpy(addr, target_addr, len);
        !           435:     addr->sa_family = tswap16(target_addr->sa_family);
        !           436: }
        !           437: 
        !           438: static inline void host_to_target_sockaddr(struct target_sockaddr *target_addr,
        !           439:                                            struct sockaddr *addr,
        !           440:                                            socklen_t len)
        !           441: {
        !           442:     memcpy(target_addr, addr, len);
        !           443:     target_addr->sa_family = tswap16(addr->sa_family);
        !           444: }
        !           445: 
        !           446: static inline void target_to_host_cmsg(struct msghdr *msgh,
        !           447:                                        struct target_msghdr *target_msgh)
        !           448: {
        !           449:     struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
        !           450:     struct target_cmsghdr *target_cmsg = TARGET_CMSG_FIRSTHDR(target_msgh);
        !           451:     socklen_t space = 0;
        !           452: 
        !           453:     while (cmsg && target_cmsg) {
        !           454:         void *data = CMSG_DATA(cmsg);
        !           455:         void *target_data = TARGET_CMSG_DATA(target_cmsg);
        !           456: 
        !           457:         int len = tswapl(target_cmsg->cmsg_len) 
        !           458:                   - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
        !           459: 
        !           460:         space += CMSG_SPACE(len);
        !           461:         if (space > msgh->msg_controllen) {
        !           462:             space -= CMSG_SPACE(len);
        !           463:             gemu_log("Host cmsg overflow");
        !           464:             break;
        !           465:         }
        !           466: 
        !           467:         cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
        !           468:         cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
        !           469:         cmsg->cmsg_len = CMSG_LEN(len);
        !           470: 
        !           471:         if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
        !           472:             gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
        !           473:             memcpy(data, target_data, len);
        !           474:         } else {
        !           475:             int *fd = (int *)data;
        !           476:             int *target_fd = (int *)target_data;
        !           477:             int i, numfds = len / sizeof(int);
        !           478: 
        !           479:             for (i = 0; i < numfds; i++)
        !           480:                 fd[i] = tswap32(target_fd[i]);
        !           481:         }
        !           482: 
        !           483:         cmsg = CMSG_NXTHDR(msgh, cmsg);
        !           484:         target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
        !           485:     }
        !           486: 
        !           487:     msgh->msg_controllen = space;
        !           488: }
        !           489: 
        !           490: static inline void host_to_target_cmsg(struct target_msghdr *target_msgh,
        !           491:                                        struct msghdr *msgh)
        !           492: {
        !           493:     struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
        !           494:     struct target_cmsghdr *target_cmsg = TARGET_CMSG_FIRSTHDR(target_msgh);
        !           495:     socklen_t space = 0;
        !           496: 
        !           497:     while (cmsg && target_cmsg) {
        !           498:         void *data = CMSG_DATA(cmsg);
        !           499:         void *target_data = TARGET_CMSG_DATA(target_cmsg);
        !           500: 
        !           501:         int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
        !           502: 
        !           503:         space += TARGET_CMSG_SPACE(len);
        !           504:         if (space > tswapl(target_msgh->msg_controllen)) {
        !           505:             space -= TARGET_CMSG_SPACE(len);
        !           506:             gemu_log("Target cmsg overflow");
        !           507:             break;
        !           508:         }
        !           509: 
        !           510:         target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
        !           511:         target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
        !           512:         target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
        !           513: 
        !           514:         if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
        !           515:             gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
        !           516:             memcpy(target_data, data, len);
        !           517:         } else {
        !           518:             int *fd = (int *)data;
        !           519:             int *target_fd = (int *)target_data;
        !           520:             int i, numfds = len / sizeof(int);
        !           521: 
        !           522:             for (i = 0; i < numfds; i++)
        !           523:                 target_fd[i] = tswap32(fd[i]);
        !           524:         }
        !           525: 
        !           526:         cmsg = CMSG_NXTHDR(msgh, cmsg);
        !           527:         target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
        !           528:     }
        !           529: 
        !           530:     msgh->msg_controllen = tswapl(space);
        !           531: }
        !           532: 
        !           533: static long do_setsockopt(int sockfd, int level, int optname, 
        !           534:                           void *optval, socklen_t optlen)
        !           535: {
        !           536:     int val, ret;
        !           537:             
        !           538:     switch(level) {
        !           539:     case SOL_TCP:
        !           540:         /* TCP options all take an 'int' value.  */
        !           541:         if (optlen < sizeof(uint32_t))
        !           542:             return -EINVAL;
        !           543:         
        !           544:         if (get_user(val, (uint32_t *)optval))
        !           545:             return -EFAULT;
        !           546:         ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
        !           547:         break;
        !           548:     case SOL_IP:
        !           549:         switch(optname) {
        !           550:         case IP_TOS:
        !           551:         case IP_TTL:
        !           552:         case IP_HDRINCL:
        !           553:         case IP_ROUTER_ALERT:
        !           554:         case IP_RECVOPTS:
        !           555:         case IP_RETOPTS:
        !           556:         case IP_PKTINFO:
        !           557:         case IP_MTU_DISCOVER:
        !           558:         case IP_RECVERR:
        !           559:         case IP_RECVTOS:
        !           560: #ifdef IP_FREEBIND
        !           561:         case IP_FREEBIND:
        !           562: #endif
        !           563:         case IP_MULTICAST_TTL:
        !           564:         case IP_MULTICAST_LOOP:
        !           565:             val = 0;
        !           566:             if (optlen >= sizeof(uint32_t)) {
        !           567:                 if (get_user(val, (uint32_t *)optval))
        !           568:                     return -EFAULT;
        !           569:             } else if (optlen >= 1) {
        !           570:                 if (get_user(val, (uint8_t *)optval))
        !           571:                     return -EFAULT;
        !           572:             }
        !           573:             ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
        !           574:             break;
        !           575:         default:
        !           576:             goto unimplemented;
        !           577:         }
        !           578:         break;
        !           579:     case SOL_SOCKET:
        !           580:         switch (optname) {
        !           581:             /* Options with 'int' argument.  */
        !           582:         case SO_DEBUG:
        !           583:         case SO_REUSEADDR:
        !           584:         case SO_TYPE:
        !           585:         case SO_ERROR:
        !           586:         case SO_DONTROUTE:
        !           587:         case SO_BROADCAST:
        !           588:         case SO_SNDBUF:
        !           589:         case SO_RCVBUF:
        !           590:         case SO_KEEPALIVE:
        !           591:         case SO_OOBINLINE:
        !           592:         case SO_NO_CHECK:
        !           593:         case SO_PRIORITY:
        !           594: #ifdef SO_BSDCOMPAT
        !           595:         case SO_BSDCOMPAT:
        !           596: #endif
        !           597:         case SO_PASSCRED:
        !           598:         case SO_TIMESTAMP:
        !           599:         case SO_RCVLOWAT:
        !           600:         case SO_RCVTIMEO:
        !           601:         case SO_SNDTIMEO:
        !           602:             if (optlen < sizeof(uint32_t))
        !           603:                 return -EINVAL;
        !           604:             if (get_user(val, (uint32_t *)optval))
        !           605:                 return -EFAULT;
        !           606:             ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
        !           607:             break;
        !           608:         default:
        !           609:             goto unimplemented;
        !           610:         }
        !           611:         break;
        !           612:     default:
        !           613:     unimplemented:
        !           614:         gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
        !           615:         ret = -ENOSYS;
        !           616:     }
        !           617:     return ret;
        !           618: }
        !           619: 
        !           620: static long do_getsockopt(int sockfd, int level, int optname, 
        !           621:                           void *optval, socklen_t *optlen)
        !           622: {
        !           623:     int len, lv, val, ret;
        !           624: 
        !           625:     switch(level) {
        !           626:     case SOL_SOCKET:
        !           627:        switch (optname) {
        !           628:        case SO_LINGER:
        !           629:        case SO_RCVTIMEO:
        !           630:        case SO_SNDTIMEO:
        !           631:        case SO_PEERCRED:
        !           632:        case SO_PEERNAME:
        !           633:            /* These don't just return a single integer */
        !           634:            goto unimplemented;
        !           635:         default:
        !           636:             goto int_case;
        !           637:         }
        !           638:         break;
        !           639:     case SOL_TCP:
        !           640:         /* TCP options all take an 'int' value.  */
        !           641:     int_case:
        !           642:         if (get_user(len, optlen))
        !           643:             return -EFAULT;
        !           644:         if (len < 0)
        !           645:             return -EINVAL;
        !           646:         lv = sizeof(int);
        !           647:         ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
        !           648:         if (ret < 0)
        !           649:             return ret;
        !           650:         val = tswap32(val);
        !           651:         if (len > lv)
        !           652:             len = lv;
        !           653:         if (copy_to_user(optval, &val, len))
        !           654:             return -EFAULT;
        !           655:         if (put_user(len, optlen))
        !           656:             return -EFAULT;
        !           657:         break;
        !           658:     case SOL_IP:
        !           659:         switch(optname) {
        !           660:         case IP_TOS:
        !           661:         case IP_TTL:
        !           662:         case IP_HDRINCL:
        !           663:         case IP_ROUTER_ALERT:
        !           664:         case IP_RECVOPTS:
        !           665:         case IP_RETOPTS:
        !           666:         case IP_PKTINFO:
        !           667:         case IP_MTU_DISCOVER:
        !           668:         case IP_RECVERR:
        !           669:         case IP_RECVTOS:
        !           670: #ifdef IP_FREEBIND
        !           671:         case IP_FREEBIND:
        !           672: #endif
        !           673:         case IP_MULTICAST_TTL:
        !           674:         case IP_MULTICAST_LOOP:
        !           675:             if (get_user(len, optlen))
        !           676:                 return -EFAULT;
        !           677:             if (len < 0)
        !           678:                 return -EINVAL;
        !           679:             lv = sizeof(int);
        !           680:             ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
        !           681:             if (ret < 0)
        !           682:                 return ret;
        !           683:             if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
        !           684:                 unsigned char ucval = val;
        !           685:                 len = 1;
        !           686:                if (put_user(len, optlen))
        !           687:                     return -EFAULT;
        !           688:                if (copy_to_user(optval,&ucval,1))
        !           689:                     return -EFAULT;
        !           690:             } else {
        !           691:                 val = tswap32(val);
        !           692:                 if (len > sizeof(int))
        !           693:                     len = sizeof(int);
        !           694:                 if (put_user(len, optlen))
        !           695:                     return -EFAULT;
        !           696:                 if (copy_to_user(optval, &val, len))
        !           697:                     return -EFAULT;
        !           698:             }
        !           699:             break;
        !           700:         default:
        !           701:             goto unimplemented;
        !           702:         }
        !           703:         break;
        !           704:     default:
        !           705:     unimplemented:
        !           706:         gemu_log("getsockopt level=%d optname=%d not yet supported\n",
        !           707:                  level, optname);
        !           708:         ret = -ENOSYS;
        !           709:         break;
        !           710:     }
        !           711:     return ret;
        !           712: }
        !           713: 
        !           714: static long do_socketcall(int num, int32_t *vptr)
        !           715: {
        !           716:     long ret;
        !           717: 
        !           718:     switch(num) {
        !           719:     case SOCKOP_socket:
        !           720:        {
        !           721:             int domain = tswap32(vptr[0]);
        !           722:             int type = tswap32(vptr[1]);
        !           723:             int protocol = tswap32(vptr[2]);
        !           724: 
        !           725:             ret = get_errno(socket(domain, type, protocol));
        !           726:        }
        !           727:         break;
        !           728:     case SOCKOP_bind:
        !           729:        {
        !           730:             int sockfd = tswap32(vptr[0]);
        !           731:             void *target_addr = (void *)tswap32(vptr[1]);
        !           732:             socklen_t addrlen = tswap32(vptr[2]);
        !           733:             void *addr = alloca(addrlen);
        !           734: 
        !           735:             target_to_host_sockaddr(addr, target_addr, addrlen);
        !           736:             ret = get_errno(bind(sockfd, addr, addrlen));
        !           737:         }
        !           738:         break;
        !           739:     case SOCKOP_connect:
        !           740:         {
        !           741:             int sockfd = tswap32(vptr[0]);
        !           742:             void *target_addr = (void *)tswap32(vptr[1]);
        !           743:             socklen_t addrlen = tswap32(vptr[2]);
        !           744:             void *addr = alloca(addrlen);
        !           745: 
        !           746:             target_to_host_sockaddr(addr, target_addr, addrlen);
        !           747:             ret = get_errno(connect(sockfd, addr, addrlen));
        !           748:         }
        !           749:         break;
        !           750:     case SOCKOP_listen:
        !           751:         {
        !           752:             int sockfd = tswap32(vptr[0]);
        !           753:             int backlog = tswap32(vptr[1]);
        !           754: 
        !           755:             ret = get_errno(listen(sockfd, backlog));
        !           756:         }
        !           757:         break;
        !           758:     case SOCKOP_accept:
        !           759:         {
        !           760:             int sockfd = tswap32(vptr[0]);
        !           761:             void *target_addr = (void *)tswap32(vptr[1]);
        !           762:             uint32_t *target_addrlen = (void *)tswap32(vptr[2]);
        !           763:             socklen_t addrlen = tswap32(*target_addrlen);
        !           764:             void *addr = alloca(addrlen);
        !           765: 
        !           766:             ret = get_errno(accept(sockfd, addr, &addrlen));
        !           767:             if (!is_error(ret)) {
        !           768:                 host_to_target_sockaddr(target_addr, addr, addrlen);
        !           769:                 *target_addrlen = tswap32(addrlen);
        !           770:             }
        !           771:         }
        !           772:         break;
        !           773:     case SOCKOP_getsockname:
        !           774:         {
        !           775:             int sockfd = tswap32(vptr[0]);
        !           776:             void *target_addr = (void *)tswap32(vptr[1]);
        !           777:             uint32_t *target_addrlen = (void *)tswap32(vptr[2]);
        !           778:             socklen_t addrlen = tswap32(*target_addrlen);
        !           779:             void *addr = alloca(addrlen);
        !           780: 
        !           781:             ret = get_errno(getsockname(sockfd, addr, &addrlen));
        !           782:             if (!is_error(ret)) {
        !           783:                 host_to_target_sockaddr(target_addr, addr, addrlen);
        !           784:                 *target_addrlen = tswap32(addrlen);
        !           785:             }
        !           786:         }
        !           787:         break;
        !           788:     case SOCKOP_getpeername:
        !           789:         {
        !           790:             int sockfd = tswap32(vptr[0]);
        !           791:             void *target_addr = (void *)tswap32(vptr[1]);
        !           792:             uint32_t *target_addrlen = (void *)tswap32(vptr[2]);
        !           793:             socklen_t addrlen = tswap32(*target_addrlen);
        !           794:             void *addr = alloca(addrlen);
        !           795: 
        !           796:             ret = get_errno(getpeername(sockfd, addr, &addrlen));
        !           797:             if (!is_error(ret)) {
        !           798:                 host_to_target_sockaddr(target_addr, addr, addrlen);
        !           799:                 *target_addrlen = tswap32(addrlen);
        !           800:             }
        !           801:         }
        !           802:         break;
        !           803:     case SOCKOP_socketpair:
        !           804:         {
        !           805:             int domain = tswap32(vptr[0]);
        !           806:             int type = tswap32(vptr[1]);
        !           807:             int protocol = tswap32(vptr[2]);
        !           808:             int32_t *target_tab = (void *)tswap32(vptr[3]);
        !           809:             int tab[2];
        !           810: 
        !           811:             ret = get_errno(socketpair(domain, type, protocol, tab));
        !           812:             if (!is_error(ret)) {
        !           813:                 target_tab[0] = tswap32(tab[0]);
        !           814:                 target_tab[1] = tswap32(tab[1]);
        !           815:             }
        !           816:         }
        !           817:         break;
        !           818:     case SOCKOP_send:
        !           819:         {
        !           820:             int sockfd = tswap32(vptr[0]);
        !           821:             void *msg = (void *)tswap32(vptr[1]);
        !           822:             size_t len = tswap32(vptr[2]);
        !           823:             int flags = tswap32(vptr[3]);
        !           824: 
        !           825:             ret = get_errno(send(sockfd, msg, len, flags));
        !           826:         }
        !           827:         break;
        !           828:     case SOCKOP_recv:
        !           829:         {
        !           830:             int sockfd = tswap32(vptr[0]);
        !           831:             void *msg = (void *)tswap32(vptr[1]);
        !           832:             size_t len = tswap32(vptr[2]);
        !           833:             int flags = tswap32(vptr[3]);
        !           834: 
        !           835:             ret = get_errno(recv(sockfd, msg, len, flags));
        !           836:         }
        !           837:         break;
        !           838:     case SOCKOP_sendto:
        !           839:         {
        !           840:             int sockfd = tswap32(vptr[0]);
        !           841:             void *msg = (void *)tswap32(vptr[1]);
        !           842:             size_t len = tswap32(vptr[2]);
        !           843:             int flags = tswap32(vptr[3]);
        !           844:             void *target_addr = (void *)tswap32(vptr[4]);
        !           845:             socklen_t addrlen = tswap32(vptr[5]);
        !           846:             void *addr = alloca(addrlen);
        !           847: 
        !           848:             target_to_host_sockaddr(addr, target_addr, addrlen);
        !           849:             ret = get_errno(sendto(sockfd, msg, len, flags, addr, addrlen));
        !           850:         }
        !           851:         break;
        !           852:     case SOCKOP_recvfrom:
        !           853:         {
        !           854:             int sockfd = tswap32(vptr[0]);
        !           855:             void *msg = (void *)tswap32(vptr[1]);
        !           856:             size_t len = tswap32(vptr[2]);
        !           857:             int flags = tswap32(vptr[3]);
        !           858:             void *target_addr = (void *)tswap32(vptr[4]);
        !           859:             uint32_t *target_addrlen = (void *)tswap32(vptr[5]);
        !           860:             socklen_t addrlen = tswap32(*target_addrlen);
        !           861:             void *addr = alloca(addrlen);
        !           862: 
        !           863:             ret = get_errno(recvfrom(sockfd, msg, len, flags, addr, &addrlen));
        !           864:             if (!is_error(ret)) {
        !           865:                 host_to_target_sockaddr(target_addr, addr, addrlen);
        !           866:                 *target_addrlen = tswap32(addrlen);
        !           867:             }
        !           868:         }
        !           869:         break;
        !           870:     case SOCKOP_shutdown:
        !           871:         {
        !           872:             int sockfd = tswap32(vptr[0]);
        !           873:             int how = tswap32(vptr[1]);
        !           874: 
        !           875:             ret = get_errno(shutdown(sockfd, how));
        !           876:         }
        !           877:         break;
        !           878:     case SOCKOP_sendmsg:
        !           879:     case SOCKOP_recvmsg:
        !           880:         {
        !           881:             int fd;
        !           882:             struct target_msghdr *msgp;
        !           883:             struct msghdr msg;
        !           884:             int flags, count, i;
        !           885:             struct iovec *vec;
        !           886:             struct target_iovec *target_vec;
        !           887: 
        !           888:             msgp = (void *)tswap32(vptr[1]);
        !           889:             msg.msg_name = (void *)tswapl(msgp->msg_name);
        !           890:             msg.msg_namelen = tswapl(msgp->msg_namelen);
        !           891:             msg.msg_controllen = 2 * tswapl(msgp->msg_controllen);
        !           892:             msg.msg_control = alloca(msg.msg_controllen);
        !           893:             msg.msg_flags = tswap32(msgp->msg_flags);
        !           894: 
        !           895:             count = tswapl(msgp->msg_iovlen);
        !           896:             vec = alloca(count * sizeof(struct iovec));
        !           897:             target_vec = (void *)tswapl(msgp->msg_iov);
        !           898:             for(i = 0;i < count; i++) {
        !           899:                 vec[i].iov_base = (void *)tswapl(target_vec[i].iov_base);
        !           900:                 vec[i].iov_len = tswapl(target_vec[i].iov_len);
        !           901:             }
        !           902:             msg.msg_iovlen = count;
        !           903:             msg.msg_iov = vec;
        !           904: 
        !           905:             fd = tswap32(vptr[0]);
        !           906:             flags = tswap32(vptr[2]);
        !           907:             if (num == SOCKOP_sendmsg) {
        !           908:                 target_to_host_cmsg(&msg, msgp);
        !           909:                 ret = get_errno(sendmsg(fd, &msg, flags));
        !           910:             } else {
        !           911:                 ret = get_errno(recvmsg(fd, &msg, flags));
        !           912:                 if (!is_error(ret))
        !           913:                   host_to_target_cmsg(msgp, &msg);
        !           914:             }
        !           915:         }
        !           916:         break;
        !           917:     case SOCKOP_setsockopt:
        !           918:         {
        !           919:             int sockfd = tswap32(vptr[0]);
        !           920:             int level = tswap32(vptr[1]);
        !           921:             int optname = tswap32(vptr[2]);
        !           922:             void *optval = (void *)tswap32(vptr[3]);
        !           923:             socklen_t optlen = tswap32(vptr[4]);
        !           924: 
        !           925:             ret = do_setsockopt(sockfd, level, optname, optval, optlen);
        !           926:         }
        !           927:         break;
        !           928:     case SOCKOP_getsockopt:
        !           929:         {
        !           930:             int sockfd = tswap32(vptr[0]);
        !           931:             int level = tswap32(vptr[1]);
        !           932:             int optname = tswap32(vptr[2]);
        !           933:             void *optval = (void *)tswap32(vptr[3]);
        !           934:             uint32_t *poptlen = (void *)tswap32(vptr[4]);
        !           935: 
        !           936:             ret = do_getsockopt(sockfd, level, optname, optval, poptlen);
        !           937:         }
        !           938:         break;
        !           939:     default:
        !           940:         gemu_log("Unsupported socketcall: %d\n", num);
        !           941:         ret = -ENOSYS;
        !           942:         break;
        !           943:     }
        !           944:     return ret;
        !           945: }
        !           946: 
        !           947: 
        !           948: #define N_SHM_REGIONS  32
        !           949: 
        !           950: static struct shm_region {
        !           951:     uint32_t   start;
        !           952:     uint32_t   size;
        !           953: } shm_regions[N_SHM_REGIONS];
        !           954: 
        !           955: static long do_ipc(long call, long first, long second, long third,
        !           956:                   long ptr, long fifth)
        !           957: {
        !           958:     int version;
        !           959:     long ret = 0;
        !           960:     unsigned long raddr;
        !           961:     struct shmid_ds shm_info;
        !           962:     int i;
        !           963: 
        !           964:     version = call >> 16;
        !           965:     call &= 0xffff;
        !           966: 
        !           967:     switch (call) {
        !           968:     case IPCOP_shmat:
        !           969:        /* SHM_* flags are the same on all linux platforms */
        !           970:        ret = get_errno((long) shmat(first, (void *) ptr, second));
        !           971:         if (is_error(ret))
        !           972:             break;
        !           973:         raddr = ret;
        !           974:        /* find out the length of the shared memory segment */
        !           975:         
        !           976:         ret = get_errno(shmctl(first, IPC_STAT, &shm_info));
        !           977:         if (is_error(ret)) {
        !           978:             /* can't get length, bail out */
        !           979:             shmdt((void *) raddr);
        !           980:            break;
        !           981:        }
        !           982:        page_set_flags(raddr, raddr + shm_info.shm_segsz,
        !           983:                       PAGE_VALID | PAGE_READ |
        !           984:                       ((second & SHM_RDONLY)? 0: PAGE_WRITE));
        !           985:        for (i = 0; i < N_SHM_REGIONS; ++i) {
        !           986:            if (shm_regions[i].start == 0) {
        !           987:                shm_regions[i].start = raddr;
        !           988:                shm_regions[i].size = shm_info.shm_segsz;
        !           989:                 break;
        !           990:            }
        !           991:        }
        !           992:        if (put_user(raddr, (uint32_t *)third))
        !           993:             return -EFAULT;
        !           994:         ret = 0;
        !           995:        break;
        !           996:     case IPCOP_shmdt:
        !           997:        for (i = 0; i < N_SHM_REGIONS; ++i) {
        !           998:            if (shm_regions[i].start == ptr) {
        !           999:                shm_regions[i].start = 0;
        !          1000:                page_set_flags(ptr, shm_regions[i].size, 0);
        !          1001:                break;
        !          1002:            }
        !          1003:        }
        !          1004:        ret = get_errno(shmdt((void *) ptr));
        !          1005:        break;
        !          1006: 
        !          1007:     case IPCOP_shmget:
        !          1008:        /* IPC_* flag values are the same on all linux platforms */
        !          1009:        ret = get_errno(shmget(first, second, third));
        !          1010:        break;
        !          1011: 
        !          1012:        /* IPC_* and SHM_* command values are the same on all linux platforms */
        !          1013:     case IPCOP_shmctl:
        !          1014:         switch(second) {
        !          1015:         case IPC_RMID:
        !          1016:         case SHM_LOCK:
        !          1017:         case SHM_UNLOCK:
        !          1018:             ret = get_errno(shmctl(first, second, NULL));
        !          1019:             break;
        !          1020:         default:
        !          1021:             goto unimplemented;
        !          1022:         }
        !          1023:         break;
        !          1024:     default:
        !          1025:     unimplemented:
        !          1026:        gemu_log("Unsupported ipc call: %ld (version %d)\n", call, version);
        !          1027:        ret = -ENOSYS;
        !          1028:        break;
        !          1029:     }
        !          1030:     return ret;
        !          1031: }
        !          1032: 
        !          1033: /* kernel structure types definitions */
        !          1034: #define IFNAMSIZ        16
        !          1035: 
        !          1036: #define STRUCT(name, list...) STRUCT_ ## name,
        !          1037: #define STRUCT_SPECIAL(name) STRUCT_ ## name,
        !          1038: enum {
        !          1039: #include "syscall_types.h"
        !          1040: };
        !          1041: #undef STRUCT
        !          1042: #undef STRUCT_SPECIAL
        !          1043: 
        !          1044: #define STRUCT(name, list...) const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
        !          1045: #define STRUCT_SPECIAL(name)
        !          1046: #include "syscall_types.h"
        !          1047: #undef STRUCT
        !          1048: #undef STRUCT_SPECIAL
        !          1049: 
        !          1050: typedef struct IOCTLEntry {
        !          1051:     unsigned int target_cmd;
        !          1052:     unsigned int host_cmd;
        !          1053:     const char *name;
        !          1054:     int access;
        !          1055:     const argtype arg_type[5];
        !          1056: } IOCTLEntry;
        !          1057: 
        !          1058: #define IOC_R 0x0001
        !          1059: #define IOC_W 0x0002
        !          1060: #define IOC_RW (IOC_R | IOC_W)
        !          1061: 
        !          1062: #define MAX_STRUCT_SIZE 4096
        !          1063: 
        !          1064: IOCTLEntry ioctl_entries[] = {
        !          1065: #define IOCTL(cmd, access, types...) \
        !          1066:     { TARGET_ ## cmd, cmd, #cmd, access, { types } },
        !          1067: #include "ioctls.h"
        !          1068:     { 0, 0, },
        !          1069: };
        !          1070: 
        !          1071: static long do_ioctl(long fd, long cmd, long arg)
        !          1072: {
        !          1073:     const IOCTLEntry *ie;
        !          1074:     const argtype *arg_type;
        !          1075:     long ret;
        !          1076:     uint8_t buf_temp[MAX_STRUCT_SIZE];
        !          1077: 
        !          1078:     ie = ioctl_entries;
        !          1079:     for(;;) {
        !          1080:         if (ie->target_cmd == 0) {
        !          1081:             gemu_log("Unsupported ioctl: cmd=0x%04lx\n", cmd);
        !          1082:             return -ENOSYS;
        !          1083:         }
        !          1084:         if (ie->target_cmd == cmd)
        !          1085:             break;
        !          1086:         ie++;
        !          1087:     }
        !          1088:     arg_type = ie->arg_type;
        !          1089: #if defined(DEBUG)
        !          1090:     gemu_log("ioctl: cmd=0x%04lx (%s)\n", cmd, ie->name);
        !          1091: #endif
        !          1092:     switch(arg_type[0]) {
        !          1093:     case TYPE_NULL:
        !          1094:         /* no argument */
        !          1095:         ret = get_errno(ioctl(fd, ie->host_cmd));
        !          1096:         break;
        !          1097:     case TYPE_PTRVOID:
        !          1098:     case TYPE_INT:
        !          1099:         /* int argment */
        !          1100:         ret = get_errno(ioctl(fd, ie->host_cmd, arg));
        !          1101:         break;
        !          1102:     case TYPE_PTR:
        !          1103:         arg_type++;
        !          1104:         switch(ie->access) {
        !          1105:         case IOC_R:
        !          1106:             ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
        !          1107:             if (!is_error(ret)) {
        !          1108:                 thunk_convert((void *)arg, buf_temp, arg_type, THUNK_TARGET);
        !          1109:             }
        !          1110:             break;
        !          1111:         case IOC_W:
        !          1112:             thunk_convert(buf_temp, (void *)arg, arg_type, THUNK_HOST);
        !          1113:             ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
        !          1114:             break;
        !          1115:         default:
        !          1116:         case IOC_RW:
        !          1117:             thunk_convert(buf_temp, (void *)arg, arg_type, THUNK_HOST);
        !          1118:             ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
        !          1119:             if (!is_error(ret)) {
        !          1120:                 thunk_convert((void *)arg, buf_temp, arg_type, THUNK_TARGET);
        !          1121:             }
        !          1122:             break;
        !          1123:         }
        !          1124:         break;
        !          1125:     default:
        !          1126:         gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n", cmd, arg_type[0]);
        !          1127:         ret = -ENOSYS;
        !          1128:         break;
        !          1129:     }
        !          1130:     return ret;
        !          1131: }
        !          1132: 
        !          1133: bitmask_transtbl iflag_tbl[] = {
        !          1134:         { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
        !          1135:         { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
        !          1136:         { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
        !          1137:         { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
        !          1138:         { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
        !          1139:         { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
        !          1140:         { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
        !          1141:         { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
        !          1142:         { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
        !          1143:         { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
        !          1144:         { TARGET_IXON, TARGET_IXON, IXON, IXON },
        !          1145:         { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
        !          1146:         { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
        !          1147:         { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
        !          1148:         { 0, 0, 0, 0 }
        !          1149: };
        !          1150: 
        !          1151: bitmask_transtbl oflag_tbl[] = {
        !          1152:        { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
        !          1153:        { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
        !          1154:        { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
        !          1155:        { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
        !          1156:        { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
        !          1157:        { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
        !          1158:        { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
        !          1159:        { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
        !          1160:        { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
        !          1161:        { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
        !          1162:        { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
        !          1163:        { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
        !          1164:        { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
        !          1165:        { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
        !          1166:        { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
        !          1167:        { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
        !          1168:        { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
        !          1169:        { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
        !          1170:        { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
        !          1171:        { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
        !          1172:        { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
        !          1173:        { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
        !          1174:        { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
        !          1175:        { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
        !          1176:        { 0, 0, 0, 0 }
        !          1177: };
        !          1178: 
        !          1179: bitmask_transtbl cflag_tbl[] = {
        !          1180:        { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
        !          1181:        { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
        !          1182:        { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
        !          1183:        { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
        !          1184:        { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
        !          1185:        { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
        !          1186:        { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
        !          1187:        { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
        !          1188:        { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
        !          1189:        { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
        !          1190:        { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
        !          1191:        { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
        !          1192:        { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
        !          1193:        { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
        !          1194:        { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
        !          1195:        { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
        !          1196:        { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
        !          1197:        { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
        !          1198:        { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
        !          1199:        { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
        !          1200:        { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
        !          1201:        { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
        !          1202:        { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
        !          1203:        { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
        !          1204:        { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
        !          1205:        { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
        !          1206:        { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
        !          1207:        { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
        !          1208:        { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
        !          1209:        { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
        !          1210:        { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
        !          1211:        { 0, 0, 0, 0 }
        !          1212: };
        !          1213: 
        !          1214: bitmask_transtbl lflag_tbl[] = {
        !          1215:        { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
        !          1216:        { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
        !          1217:        { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
        !          1218:        { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
        !          1219:        { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
        !          1220:        { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
        !          1221:        { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
        !          1222:        { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
        !          1223:        { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
        !          1224:        { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
        !          1225:        { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
        !          1226:        { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
        !          1227:        { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
        !          1228:        { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
        !          1229:        { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
        !          1230:        { 0, 0, 0, 0 }
        !          1231: };
        !          1232: 
        !          1233: static void target_to_host_termios (void *dst, const void *src)
        !          1234: {
        !          1235:     struct host_termios *host = dst;
        !          1236:     const struct target_termios *target = src;
        !          1237:     
        !          1238:     host->c_iflag = 
        !          1239:         target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
        !          1240:     host->c_oflag = 
        !          1241:         target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
        !          1242:     host->c_cflag = 
        !          1243:         target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
        !          1244:     host->c_lflag = 
        !          1245:         target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
        !          1246:     host->c_line = target->c_line;
        !          1247:     
        !          1248:     host->c_cc[VINTR] = target->c_cc[TARGET_VINTR]; 
        !          1249:     host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT]; 
        !          1250:     host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];       
        !          1251:     host->c_cc[VKILL] = target->c_cc[TARGET_VKILL]; 
        !          1252:     host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];   
        !          1253:     host->c_cc[VTIME] = target->c_cc[TARGET_VTIME]; 
        !          1254:     host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];   
        !          1255:     host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC]; 
        !          1256:     host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];       
        !          1257:     host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP]; 
        !          1258:     host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP]; 
        !          1259:     host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];   
        !          1260:     host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];   
        !          1261:     host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];   
        !          1262:     host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];     
        !          1263:     host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];       
        !          1264:     host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2]; 
        !          1265: }
        !          1266:   
        !          1267: static void host_to_target_termios (void *dst, const void *src)
        !          1268: {
        !          1269:     struct target_termios *target = dst;
        !          1270:     const struct host_termios *host = src;
        !          1271: 
        !          1272:     target->c_iflag = 
        !          1273:         tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
        !          1274:     target->c_oflag = 
        !          1275:         tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
        !          1276:     target->c_cflag = 
        !          1277:         tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
        !          1278:     target->c_lflag = 
        !          1279:         tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
        !          1280:     target->c_line = host->c_line;
        !          1281:   
        !          1282:     target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
        !          1283:     target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
        !          1284:     target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
        !          1285:     target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
        !          1286:     target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
        !          1287:     target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
        !          1288:     target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
        !          1289:     target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
        !          1290:     target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
        !          1291:     target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
        !          1292:     target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
        !          1293:     target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
        !          1294:     target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
        !          1295:     target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
        !          1296:     target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
        !          1297:     target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
        !          1298:     target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
        !          1299: }
        !          1300: 
        !          1301: StructEntry struct_termios_def = {
        !          1302:     .convert = { host_to_target_termios, target_to_host_termios },
        !          1303:     .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
        !          1304:     .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
        !          1305: };
        !          1306: 
        !          1307: static bitmask_transtbl mmap_flags_tbl[] = {
        !          1308:        { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
        !          1309:        { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
        !          1310:        { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
        !          1311:        { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
        !          1312:        { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
        !          1313:        { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
        !          1314:        { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
        !          1315:        { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
        !          1316:        { 0, 0, 0, 0 }
        !          1317: };
        !          1318: 
        !          1319: static bitmask_transtbl fcntl_flags_tbl[] = {
        !          1320:        { TARGET_O_ACCMODE,   TARGET_O_WRONLY,    O_ACCMODE,   O_WRONLY,    },
        !          1321:        { TARGET_O_ACCMODE,   TARGET_O_RDWR,      O_ACCMODE,   O_RDWR,      },
        !          1322:        { TARGET_O_CREAT,     TARGET_O_CREAT,     O_CREAT,     O_CREAT,     },
        !          1323:        { TARGET_O_EXCL,      TARGET_O_EXCL,      O_EXCL,      O_EXCL,      },
        !          1324:        { TARGET_O_NOCTTY,    TARGET_O_NOCTTY,    O_NOCTTY,    O_NOCTTY,    },
        !          1325:        { TARGET_O_TRUNC,     TARGET_O_TRUNC,     O_TRUNC,     O_TRUNC,     },
        !          1326:        { TARGET_O_APPEND,    TARGET_O_APPEND,    O_APPEND,    O_APPEND,    },
        !          1327:        { TARGET_O_NONBLOCK,  TARGET_O_NONBLOCK,  O_NONBLOCK,  O_NONBLOCK,  },
        !          1328:        { TARGET_O_SYNC,      TARGET_O_SYNC,      O_SYNC,      O_SYNC,      },
        !          1329:        { TARGET_FASYNC,      TARGET_FASYNC,      FASYNC,      FASYNC,      },
        !          1330:        { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
        !          1331:        { TARGET_O_NOFOLLOW,  TARGET_O_NOFOLLOW,  O_NOFOLLOW,  O_NOFOLLOW,  },
        !          1332:        { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
        !          1333: #if defined(O_DIRECT)
        !          1334:        { TARGET_O_DIRECT,    TARGET_O_DIRECT,    O_DIRECT,    O_DIRECT,    },
        !          1335: #endif
        !          1336:        { 0, 0, 0, 0 }
        !          1337: };
        !          1338: 
        !          1339: #if defined(TARGET_I386)
        !          1340: 
        !          1341: /* NOTE: there is really one LDT for all the threads */
        !          1342: uint8_t *ldt_table;
        !          1343: 
        !          1344: static int read_ldt(void *ptr, unsigned long bytecount)
        !          1345: {
        !          1346:     int size;
        !          1347: 
        !          1348:     if (!ldt_table)
        !          1349:         return 0;
        !          1350:     size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
        !          1351:     if (size > bytecount)
        !          1352:         size = bytecount;
        !          1353:     memcpy(ptr, ldt_table, size);
        !          1354:     return size;
        !          1355: }
        !          1356: 
        !          1357: /* XXX: add locking support */
        !          1358: static int write_ldt(CPUX86State *env, 
        !          1359:                      void *ptr, unsigned long bytecount, int oldmode)
        !          1360: {
        !          1361:     struct target_modify_ldt_ldt_s ldt_info;
        !          1362:     int seg_32bit, contents, read_exec_only, limit_in_pages;
        !          1363:     int seg_not_present, useable;
        !          1364:     uint32_t *lp, entry_1, entry_2;
        !          1365: 
        !          1366:     if (bytecount != sizeof(ldt_info))
        !          1367:         return -EINVAL;
        !          1368:     memcpy(&ldt_info, ptr, sizeof(ldt_info));
        !          1369:     tswap32s(&ldt_info.entry_number);
        !          1370:     tswapls((long *)&ldt_info.base_addr);
        !          1371:     tswap32s(&ldt_info.limit);
        !          1372:     tswap32s(&ldt_info.flags);
        !          1373:     
        !          1374:     if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
        !          1375:         return -EINVAL;
        !          1376:     seg_32bit = ldt_info.flags & 1;
        !          1377:     contents = (ldt_info.flags >> 1) & 3;
        !          1378:     read_exec_only = (ldt_info.flags >> 3) & 1;
        !          1379:     limit_in_pages = (ldt_info.flags >> 4) & 1;
        !          1380:     seg_not_present = (ldt_info.flags >> 5) & 1;
        !          1381:     useable = (ldt_info.flags >> 6) & 1;
        !          1382: 
        !          1383:     if (contents == 3) {
        !          1384:         if (oldmode)
        !          1385:             return -EINVAL;
        !          1386:         if (seg_not_present == 0)
        !          1387:             return -EINVAL;
        !          1388:     }
        !          1389:     /* allocate the LDT */
        !          1390:     if (!ldt_table) {
        !          1391:         ldt_table = malloc(TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
        !          1392:         if (!ldt_table)
        !          1393:             return -ENOMEM;
        !          1394:         memset(ldt_table, 0, TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
        !          1395:         env->ldt.base = (long)ldt_table;
        !          1396:         env->ldt.limit = 0xffff;
        !          1397:     }
        !          1398: 
        !          1399:     /* NOTE: same code as Linux kernel */
        !          1400:     /* Allow LDTs to be cleared by the user. */
        !          1401:     if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
        !          1402:         if (oldmode ||
        !          1403:             (contents == 0             &&
        !          1404:              read_exec_only == 1       &&
        !          1405:              seg_32bit == 0            &&
        !          1406:              limit_in_pages == 0       &&
        !          1407:              seg_not_present == 1      &&
        !          1408:              useable == 0 )) {
        !          1409:             entry_1 = 0;
        !          1410:             entry_2 = 0;
        !          1411:             goto install;
        !          1412:         }
        !          1413:     }
        !          1414:     
        !          1415:     entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
        !          1416:         (ldt_info.limit & 0x0ffff);
        !          1417:     entry_2 = (ldt_info.base_addr & 0xff000000) |
        !          1418:         ((ldt_info.base_addr & 0x00ff0000) >> 16) |
        !          1419:         (ldt_info.limit & 0xf0000) |
        !          1420:         ((read_exec_only ^ 1) << 9) |
        !          1421:         (contents << 10) |
        !          1422:         ((seg_not_present ^ 1) << 15) |
        !          1423:         (seg_32bit << 22) |
        !          1424:         (limit_in_pages << 23) |
        !          1425:         0x7000;
        !          1426:     if (!oldmode)
        !          1427:         entry_2 |= (useable << 20);
        !          1428: 
        !          1429:     /* Install the new entry ...  */
        !          1430: install:
        !          1431:     lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
        !          1432:     lp[0] = tswap32(entry_1);
        !          1433:     lp[1] = tswap32(entry_2);
        !          1434:     return 0;
        !          1435: }
        !          1436: 
        !          1437: /* specific and weird i386 syscalls */
        !          1438: int do_modify_ldt(CPUX86State *env, int func, void *ptr, unsigned long bytecount)
        !          1439: {
        !          1440:     int ret = -ENOSYS;
        !          1441:     
        !          1442:     switch (func) {
        !          1443:     case 0:
        !          1444:         ret = read_ldt(ptr, bytecount);
        !          1445:         break;
        !          1446:     case 1:
        !          1447:         ret = write_ldt(env, ptr, bytecount, 1);
        !          1448:         break;
        !          1449:     case 0x11:
        !          1450:         ret = write_ldt(env, ptr, bytecount, 0);
        !          1451:         break;
        !          1452:     }
        !          1453:     return ret;
        !          1454: }
        !          1455: 
        !          1456: #endif /* defined(TARGET_I386) */
        !          1457: 
        !          1458: /* this stack is the equivalent of the kernel stack associated with a
        !          1459:    thread/process */
        !          1460: #define NEW_STACK_SIZE 8192
        !          1461: 
        !          1462: static int clone_func(void *arg)
        !          1463: {
        !          1464:     CPUState *env = arg;
        !          1465:     cpu_loop(env);
        !          1466:     /* never exits */
        !          1467:     return 0;
        !          1468: }
        !          1469: 
        !          1470: int do_fork(CPUState *env, unsigned int flags, unsigned long newsp)
        !          1471: {
        !          1472:     int ret;
        !          1473:     TaskState *ts;
        !          1474:     uint8_t *new_stack;
        !          1475:     CPUState *new_env;
        !          1476:     
        !          1477:     if (flags & CLONE_VM) {
        !          1478:         ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE);
        !          1479:         memset(ts, 0, sizeof(TaskState));
        !          1480:         new_stack = ts->stack;
        !          1481:         ts->used = 1;
        !          1482:         /* add in task state list */
        !          1483:         ts->next = first_task_state;
        !          1484:         first_task_state = ts;
        !          1485:         /* we create a new CPU instance. */
        !          1486:         new_env = cpu_init();
        !          1487:         memcpy(new_env, env, sizeof(CPUState));
        !          1488: #if defined(TARGET_I386)
        !          1489:         if (!newsp)
        !          1490:             newsp = env->regs[R_ESP];
        !          1491:         new_env->regs[R_ESP] = newsp;
        !          1492:         new_env->regs[R_EAX] = 0;
        !          1493: #elif defined(TARGET_ARM)
        !          1494:         if (!newsp)
        !          1495:             newsp = env->regs[13];
        !          1496:         new_env->regs[13] = newsp;
        !          1497:         new_env->regs[0] = 0;
        !          1498: #elif defined(TARGET_SPARC)
        !          1499:         printf ("HELPME: %s:%d\n", __FILE__, __LINE__);
        !          1500: #elif defined(TARGET_PPC)
        !          1501:         if (!newsp)
        !          1502:             newsp = env->gpr[1];
        !          1503:         new_env->gpr[1] = newsp;
        !          1504:         { 
        !          1505:             int i;
        !          1506:             for (i = 7; i < 32; i++)
        !          1507:                 new_env->gpr[i] = 0;
        !          1508:         }
        !          1509: #else
        !          1510: #error unsupported target CPU
        !          1511: #endif
        !          1512:         new_env->opaque = ts;
        !          1513: #ifdef __ia64__
        !          1514:         ret = clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
        !          1515: #else
        !          1516:        ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
        !          1517: #endif
        !          1518:     } else {
        !          1519:         /* if no CLONE_VM, we consider it is a fork */
        !          1520:         if ((flags & ~CSIGNAL) != 0)
        !          1521:             return -EINVAL;
        !          1522:         ret = fork();
        !          1523:     }
        !          1524:     return ret;
        !          1525: }
        !          1526: 
        !          1527: static long do_fcntl(int fd, int cmd, unsigned long arg)
        !          1528: {
        !          1529:     struct flock fl;
        !          1530:     struct target_flock *target_fl = (void *)arg;
        !          1531:     long ret;
        !          1532:     
        !          1533:     switch(cmd) {
        !          1534:     case TARGET_F_GETLK:
        !          1535:         ret = fcntl(fd, cmd, &fl);
        !          1536:         if (ret == 0) {
        !          1537:             target_fl->l_type = tswap16(fl.l_type);
        !          1538:             target_fl->l_whence = tswap16(fl.l_whence);
        !          1539:             target_fl->l_start = tswapl(fl.l_start);
        !          1540:             target_fl->l_len = tswapl(fl.l_len);
        !          1541:             target_fl->l_pid = tswapl(fl.l_pid);
        !          1542:         }
        !          1543:         break;
        !          1544:         
        !          1545:     case TARGET_F_SETLK:
        !          1546:     case TARGET_F_SETLKW:
        !          1547:         fl.l_type = tswap16(target_fl->l_type);
        !          1548:         fl.l_whence = tswap16(target_fl->l_whence);
        !          1549:         fl.l_start = tswapl(target_fl->l_start);
        !          1550:         fl.l_len = tswapl(target_fl->l_len);
        !          1551:         fl.l_pid = tswapl(target_fl->l_pid);
        !          1552:         ret = fcntl(fd, cmd, &fl);
        !          1553:         break;
        !          1554:         
        !          1555:     case TARGET_F_GETLK64:
        !          1556:     case TARGET_F_SETLK64:
        !          1557:     case TARGET_F_SETLKW64:
        !          1558:         ret = -1;
        !          1559:         errno = EINVAL;
        !          1560:         break;
        !          1561: 
        !          1562:     case F_GETFL:
        !          1563:         ret = fcntl(fd, cmd, arg);
        !          1564:         ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
        !          1565:         break;
        !          1566: 
        !          1567:     case F_SETFL:
        !          1568:         ret = fcntl(fd, cmd, target_to_host_bitmask(arg, fcntl_flags_tbl));
        !          1569:         break;
        !          1570: 
        !          1571:     default:
        !          1572:         ret = fcntl(fd, cmd, arg);
        !          1573:         break;
        !          1574:     }
        !          1575:     return ret;
        !          1576: }
        !          1577: 
        !          1578: #ifdef USE_UID16
        !          1579: 
        !          1580: static inline int high2lowuid(int uid)
        !          1581: {
        !          1582:     if (uid > 65535)
        !          1583:         return 65534;
        !          1584:     else
        !          1585:         return uid;
        !          1586: }
        !          1587: 
        !          1588: static inline int high2lowgid(int gid)
        !          1589: {
        !          1590:     if (gid > 65535)
        !          1591:         return 65534;
        !          1592:     else
        !          1593:         return gid;
        !          1594: }
        !          1595: 
        !          1596: static inline int low2highuid(int uid)
        !          1597: {
        !          1598:     if ((int16_t)uid == -1)
        !          1599:         return -1;
        !          1600:     else
        !          1601:         return uid;
        !          1602: }
        !          1603: 
        !          1604: static inline int low2highgid(int gid)
        !          1605: {
        !          1606:     if ((int16_t)gid == -1)
        !          1607:         return -1;
        !          1608:     else
        !          1609:         return gid;
        !          1610: }
        !          1611: 
        !          1612: #endif /* USE_UID16 */
        !          1613: 
        !          1614: void syscall_init(void)
        !          1615: {
        !          1616:     IOCTLEntry *ie;
        !          1617:     const argtype *arg_type;
        !          1618:     int size;
        !          1619: 
        !          1620: #define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def); 
        !          1621: #define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def); 
        !          1622: #include "syscall_types.h"
        !          1623: #undef STRUCT
        !          1624: #undef STRUCT_SPECIAL
        !          1625: 
        !          1626:     /* we patch the ioctl size if necessary. We rely on the fact that
        !          1627:        no ioctl has all the bits at '1' in the size field */
        !          1628:     ie = ioctl_entries;
        !          1629:     while (ie->target_cmd != 0) {
        !          1630:         if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
        !          1631:             TARGET_IOC_SIZEMASK) {
        !          1632:             arg_type = ie->arg_type;
        !          1633:             if (arg_type[0] != TYPE_PTR) {
        !          1634:                 fprintf(stderr, "cannot patch size for ioctl 0x%x\n", 
        !          1635:                         ie->target_cmd);
        !          1636:                 exit(1);
        !          1637:             }
        !          1638:             arg_type++;
        !          1639:             size = thunk_type_size(arg_type, 0);
        !          1640:             ie->target_cmd = (ie->target_cmd & 
        !          1641:                               ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
        !          1642:                 (size << TARGET_IOC_SIZESHIFT);
        !          1643:         }
        !          1644:         /* automatic consistency check if same arch */
        !          1645: #if defined(__i386__) && defined(TARGET_I386)
        !          1646:         if (ie->target_cmd != ie->host_cmd) {
        !          1647:             fprintf(stderr, "ERROR: ioctl: target=0x%x host=0x%x\n", 
        !          1648:                     ie->target_cmd, ie->host_cmd);
        !          1649:         }
        !          1650: #endif
        !          1651:         ie++;
        !          1652:     }
        !          1653: }
        !          1654: 
        !          1655: long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, 
        !          1656:                 long arg4, long arg5, long arg6)
        !          1657: {
        !          1658:     long ret;
        !          1659:     struct stat st;
        !          1660:     struct kernel_statfs *stfs;
        !          1661:     
        !          1662: #ifdef DEBUG
        !          1663:     gemu_log("syscall %d", num);
        !          1664: #endif
        !          1665:     switch(num) {
        !          1666:     case TARGET_NR_exit:
        !          1667: #ifdef HAVE_GPROF
        !          1668:         _mcleanup();
        !          1669: #endif
        !          1670:         gdb_exit(cpu_env, arg1);
        !          1671:         /* XXX: should free thread stack and CPU env */
        !          1672:         _exit(arg1);
        !          1673:         ret = 0; /* avoid warning */
        !          1674:         break;
        !          1675:     case TARGET_NR_read:
        !          1676:         page_unprotect_range((void *)arg2, arg3);
        !          1677:         ret = get_errno(read(arg1, (void *)arg2, arg3));
        !          1678:         break;
        !          1679:     case TARGET_NR_write:
        !          1680:         ret = get_errno(write(arg1, (void *)arg2, arg3));
        !          1681:         break;
        !          1682:     case TARGET_NR_open:
        !          1683:         ret = get_errno(open(path((const char *)arg1),
        !          1684:                              target_to_host_bitmask(arg2, fcntl_flags_tbl),
        !          1685:                              arg3));
        !          1686:         break;
        !          1687:     case TARGET_NR_close:
        !          1688:         ret = get_errno(close(arg1));
        !          1689:         break;
        !          1690:     case TARGET_NR_brk:
        !          1691:         ret = do_brk((char *)arg1);
        !          1692:         break;
        !          1693:     case TARGET_NR_fork:
        !          1694:         ret = get_errno(do_fork(cpu_env, SIGCHLD, 0));
        !          1695:         break;
        !          1696:     case TARGET_NR_waitpid:
        !          1697:         {
        !          1698:             int *status = (int *)arg2;
        !          1699:             ret = get_errno(waitpid(arg1, status, arg3));
        !          1700:             if (!is_error(ret) && status)
        !          1701:                 tswapls((long *)&status);
        !          1702:         }
        !          1703:         break;
        !          1704:     case TARGET_NR_creat:
        !          1705:         ret = get_errno(creat((const char *)arg1, arg2));
        !          1706:         break;
        !          1707:     case TARGET_NR_link:
        !          1708:         ret = get_errno(link((const char *)arg1, (const char *)arg2));
        !          1709:         break;
        !          1710:     case TARGET_NR_unlink:
        !          1711:         ret = get_errno(unlink((const char *)arg1));
        !          1712:         break;
        !          1713:     case TARGET_NR_execve:
        !          1714:         {
        !          1715:             char **argp, **envp;
        !          1716:             int argc, envc;
        !          1717:             uint32_t *p;
        !          1718:             char **q;
        !          1719: 
        !          1720:             argc = 0;
        !          1721:             for (p = (void *)arg2; *p; p++)
        !          1722:                 argc++;
        !          1723:             envc = 0;
        !          1724:             for (p = (void *)arg3; *p; p++)
        !          1725:                 envc++;
        !          1726: 
        !          1727:             argp = alloca((argc + 1) * sizeof(void *));
        !          1728:             envp = alloca((envc + 1) * sizeof(void *));
        !          1729: 
        !          1730:             for (p = (void *)arg2, q = argp; *p; p++, q++)
        !          1731:                 *q = (void *)tswap32(*p);
        !          1732:             *q = NULL;
        !          1733: 
        !          1734:             for (p = (void *)arg3, q = envp; *p; p++, q++)
        !          1735:                 *q = (void *)tswap32(*p);
        !          1736:             *q = NULL;
        !          1737: 
        !          1738:             ret = get_errno(execve((const char *)arg1, argp, envp));
        !          1739:         }
        !          1740:         break;
        !          1741:     case TARGET_NR_chdir:
        !          1742:         ret = get_errno(chdir((const char *)arg1));
        !          1743:         break;
        !          1744: #ifdef TARGET_NR_time
        !          1745:     case TARGET_NR_time:
        !          1746:         {
        !          1747:             int *time_ptr = (int *)arg1;
        !          1748:             ret = get_errno(time((time_t *)time_ptr));
        !          1749:             if (!is_error(ret) && time_ptr)
        !          1750:                 tswap32s(time_ptr);
        !          1751:         }
        !          1752:         break;
        !          1753: #endif
        !          1754:     case TARGET_NR_mknod:
        !          1755:         ret = get_errno(mknod((const char *)arg1, arg2, arg3));
        !          1756:         break;
        !          1757:     case TARGET_NR_chmod:
        !          1758:         ret = get_errno(chmod((const char *)arg1, arg2));
        !          1759:         break;
        !          1760: #ifdef TARGET_NR_break
        !          1761:     case TARGET_NR_break:
        !          1762:         goto unimplemented;
        !          1763: #endif
        !          1764: #ifdef TARGET_NR_oldstat
        !          1765:     case TARGET_NR_oldstat:
        !          1766:         goto unimplemented;
        !          1767: #endif
        !          1768:     case TARGET_NR_lseek:
        !          1769:         ret = get_errno(lseek(arg1, arg2, arg3));
        !          1770:         break;
        !          1771:     case TARGET_NR_getpid:
        !          1772:         ret = get_errno(getpid());
        !          1773:         break;
        !          1774:     case TARGET_NR_mount:
        !          1775:         /* need to look at the data field */
        !          1776:         goto unimplemented;
        !          1777:     case TARGET_NR_umount:
        !          1778:         ret = get_errno(umount((const char *)arg1));
        !          1779:         break;
        !          1780:     case TARGET_NR_stime:
        !          1781:         {
        !          1782:             int *time_ptr = (int *)arg1;
        !          1783:             if (time_ptr)
        !          1784:                 tswap32s(time_ptr);
        !          1785:             ret = get_errno(stime((time_t *)time_ptr));
        !          1786:         }
        !          1787:         break;
        !          1788:     case TARGET_NR_ptrace:
        !          1789:         goto unimplemented;
        !          1790:     case TARGET_NR_alarm:
        !          1791:         ret = alarm(arg1);
        !          1792:         break;
        !          1793: #ifdef TARGET_NR_oldfstat
        !          1794:     case TARGET_NR_oldfstat:
        !          1795:         goto unimplemented;
        !          1796: #endif
        !          1797:     case TARGET_NR_pause:
        !          1798:         ret = get_errno(pause());
        !          1799:         break;
        !          1800:     case TARGET_NR_utime:
        !          1801:         {
        !          1802:             struct utimbuf tbuf, *tbuf1;
        !          1803:             struct target_utimbuf *target_tbuf = (void *)arg2;
        !          1804:             if (target_tbuf) {
        !          1805:                 get_user(tbuf.actime, &target_tbuf->actime);
        !          1806:                 get_user(tbuf.modtime, &target_tbuf->modtime);
        !          1807:                 tbuf1 = &tbuf;
        !          1808:             } else {
        !          1809:                 tbuf1 = NULL;
        !          1810:             }
        !          1811:             ret = get_errno(utime((const char *)arg1, tbuf1));
        !          1812:         }
        !          1813:         break;
        !          1814:     case TARGET_NR_utimes:
        !          1815:         {
        !          1816:             struct target_timeval *target_tvp = (struct target_timeval *)arg2;
        !          1817:             struct timeval *tvp, tv[2];
        !          1818:             if (target_tvp) {
        !          1819:                 target_to_host_timeval(&tv[0], &target_tvp[0]);
        !          1820:                 target_to_host_timeval(&tv[1], &target_tvp[1]);
        !          1821:                 tvp = tv;
        !          1822:             } else {
        !          1823:                 tvp = NULL;
        !          1824:             }
        !          1825:             ret = get_errno(utimes((const char *)arg1, tvp));
        !          1826:         }
        !          1827:         break;
        !          1828: #ifdef TARGET_NR_stty
        !          1829:     case TARGET_NR_stty:
        !          1830:         goto unimplemented;
        !          1831: #endif
        !          1832: #ifdef TARGET_NR_gtty
        !          1833:     case TARGET_NR_gtty:
        !          1834:         goto unimplemented;
        !          1835: #endif
        !          1836:     case TARGET_NR_access:
        !          1837:         ret = get_errno(access((const char *)arg1, arg2));
        !          1838:         break;
        !          1839:     case TARGET_NR_nice:
        !          1840:         ret = get_errno(nice(arg1));
        !          1841:         break;
        !          1842: #ifdef TARGET_NR_ftime
        !          1843:     case TARGET_NR_ftime:
        !          1844:         goto unimplemented;
        !          1845: #endif
        !          1846:     case TARGET_NR_sync:
        !          1847:         sync();
        !          1848:         ret = 0;
        !          1849:         break;
        !          1850:     case TARGET_NR_kill:
        !          1851:         ret = get_errno(kill(arg1, arg2));
        !          1852:         break;
        !          1853:     case TARGET_NR_rename:
        !          1854:         ret = get_errno(rename((const char *)arg1, (const char *)arg2));
        !          1855:         break;
        !          1856:     case TARGET_NR_mkdir:
        !          1857:         ret = get_errno(mkdir((const char *)arg1, arg2));
        !          1858:         break;
        !          1859:     case TARGET_NR_rmdir:
        !          1860:         ret = get_errno(rmdir((const char *)arg1));
        !          1861:         break;
        !          1862:     case TARGET_NR_dup:
        !          1863:         ret = get_errno(dup(arg1));
        !          1864:         break;
        !          1865:     case TARGET_NR_pipe:
        !          1866:         {
        !          1867:             int *pipe_ptr = (int *)arg1;
        !          1868:             ret = get_errno(pipe(pipe_ptr));
        !          1869:             if (!is_error(ret)) {
        !          1870:                 tswap32s(&pipe_ptr[0]);
        !          1871:                 tswap32s(&pipe_ptr[1]);
        !          1872:             }
        !          1873:         }
        !          1874:         break;
        !          1875:     case TARGET_NR_times:
        !          1876:         {
        !          1877:             struct target_tms *tmsp = (void *)arg1;
        !          1878:             struct tms tms;
        !          1879:             ret = get_errno(times(&tms));
        !          1880:             if (tmsp) {
        !          1881:                 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
        !          1882:                 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
        !          1883:                 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
        !          1884:                 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
        !          1885:             }
        !          1886:             if (!is_error(ret))
        !          1887:                 ret = host_to_target_clock_t(ret);
        !          1888:         }
        !          1889:         break;
        !          1890: #ifdef TARGET_NR_prof
        !          1891:     case TARGET_NR_prof:
        !          1892:         goto unimplemented;
        !          1893: #endif
        !          1894:     case TARGET_NR_signal:
        !          1895:         goto unimplemented;
        !          1896: 
        !          1897:     case TARGET_NR_acct:
        !          1898:         goto unimplemented;
        !          1899:     case TARGET_NR_umount2:
        !          1900:         ret = get_errno(umount2((const char *)arg1, arg2));
        !          1901:         break;
        !          1902: #ifdef TARGET_NR_lock
        !          1903:     case TARGET_NR_lock:
        !          1904:         goto unimplemented;
        !          1905: #endif
        !          1906:     case TARGET_NR_ioctl:
        !          1907:         ret = do_ioctl(arg1, arg2, arg3);
        !          1908:         break;
        !          1909:     case TARGET_NR_fcntl:
        !          1910:         ret = get_errno(do_fcntl(arg1, arg2, arg3));
        !          1911:         break;
        !          1912: #ifdef TARGET_NR_mpx
        !          1913:     case TARGET_NR_mpx:
        !          1914:         goto unimplemented;
        !          1915: #endif
        !          1916:     case TARGET_NR_setpgid:
        !          1917:         ret = get_errno(setpgid(arg1, arg2));
        !          1918:         break;
        !          1919: #ifdef TARGET_NR_ulimit
        !          1920:     case TARGET_NR_ulimit:
        !          1921:         goto unimplemented;
        !          1922: #endif
        !          1923: #ifdef TARGET_NR_oldolduname
        !          1924:     case TARGET_NR_oldolduname:
        !          1925:         goto unimplemented;
        !          1926: #endif
        !          1927:     case TARGET_NR_umask:
        !          1928:         ret = get_errno(umask(arg1));
        !          1929:         break;
        !          1930:     case TARGET_NR_chroot:
        !          1931:         ret = get_errno(chroot((const char *)arg1));
        !          1932:         break;
        !          1933:     case TARGET_NR_ustat:
        !          1934:         goto unimplemented;
        !          1935:     case TARGET_NR_dup2:
        !          1936:         ret = get_errno(dup2(arg1, arg2));
        !          1937:         break;
        !          1938:     case TARGET_NR_getppid:
        !          1939:         ret = get_errno(getppid());
        !          1940:         break;
        !          1941:     case TARGET_NR_getpgrp:
        !          1942:         ret = get_errno(getpgrp());
        !          1943:         break;
        !          1944:     case TARGET_NR_setsid:
        !          1945:         ret = get_errno(setsid());
        !          1946:         break;
        !          1947:     case TARGET_NR_sigaction:
        !          1948:         {
        !          1949:             struct target_old_sigaction *old_act = (void *)arg2;
        !          1950:             struct target_old_sigaction *old_oact = (void *)arg3;
        !          1951:             struct target_sigaction act, oact, *pact;
        !          1952:             if (old_act) {
        !          1953:                 act._sa_handler = old_act->_sa_handler;
        !          1954:                 target_siginitset(&act.sa_mask, old_act->sa_mask);
        !          1955:                 act.sa_flags = old_act->sa_flags;
        !          1956:                 act.sa_restorer = old_act->sa_restorer;
        !          1957:                 pact = &act;
        !          1958:             } else {
        !          1959:                 pact = NULL;
        !          1960:             }
        !          1961:             ret = get_errno(do_sigaction(arg1, pact, &oact));
        !          1962:             if (!is_error(ret) && old_oact) {
        !          1963:                 old_oact->_sa_handler = oact._sa_handler;
        !          1964:                 old_oact->sa_mask = oact.sa_mask.sig[0];
        !          1965:                 old_oact->sa_flags = oact.sa_flags;
        !          1966:                 old_oact->sa_restorer = oact.sa_restorer;
        !          1967:             }
        !          1968:         }
        !          1969:         break;
        !          1970:     case TARGET_NR_rt_sigaction:
        !          1971:         ret = get_errno(do_sigaction(arg1, (void *)arg2, (void *)arg3));
        !          1972:         break;
        !          1973:     case TARGET_NR_sgetmask:
        !          1974:         {
        !          1975:             sigset_t cur_set;
        !          1976:             target_ulong target_set;
        !          1977:             sigprocmask(0, NULL, &cur_set);
        !          1978:             host_to_target_old_sigset(&target_set, &cur_set);
        !          1979:             ret = target_set;
        !          1980:         }
        !          1981:         break;
        !          1982:     case TARGET_NR_ssetmask:
        !          1983:         {
        !          1984:             sigset_t set, oset, cur_set;
        !          1985:             target_ulong target_set = arg1;
        !          1986:             sigprocmask(0, NULL, &cur_set);
        !          1987:             target_to_host_old_sigset(&set, &target_set);
        !          1988:             sigorset(&set, &set, &cur_set);
        !          1989:             sigprocmask(SIG_SETMASK, &set, &oset);
        !          1990:             host_to_target_old_sigset(&target_set, &oset);
        !          1991:             ret = target_set;
        !          1992:         }
        !          1993:         break;
        !          1994:     case TARGET_NR_sigprocmask:
        !          1995:         {
        !          1996:             int how = arg1;
        !          1997:             sigset_t set, oldset, *set_ptr;
        !          1998:             target_ulong *pset = (void *)arg2, *poldset = (void *)arg3;
        !          1999:             
        !          2000:             if (pset) {
        !          2001:                 switch(how) {
        !          2002:                 case TARGET_SIG_BLOCK:
        !          2003:                     how = SIG_BLOCK;
        !          2004:                     break;
        !          2005:                 case TARGET_SIG_UNBLOCK:
        !          2006:                     how = SIG_UNBLOCK;
        !          2007:                     break;
        !          2008:                 case TARGET_SIG_SETMASK:
        !          2009:                     how = SIG_SETMASK;
        !          2010:                     break;
        !          2011:                 default:
        !          2012:                     ret = -EINVAL;
        !          2013:                     goto fail;
        !          2014:                 }
        !          2015:                 target_to_host_old_sigset(&set, pset);
        !          2016:                 set_ptr = &set;
        !          2017:             } else {
        !          2018:                 how = 0;
        !          2019:                 set_ptr = NULL;
        !          2020:             }
        !          2021:             ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
        !          2022:             if (!is_error(ret) && poldset) {
        !          2023:                 host_to_target_old_sigset(poldset, &oldset);
        !          2024:             }
        !          2025:         }
        !          2026:         break;
        !          2027:     case TARGET_NR_rt_sigprocmask:
        !          2028:         {
        !          2029:             int how = arg1;
        !          2030:             sigset_t set, oldset, *set_ptr;
        !          2031:             target_sigset_t *pset = (void *)arg2;
        !          2032:             target_sigset_t *poldset = (void *)arg3;
        !          2033:             
        !          2034:             if (pset) {
        !          2035:                 switch(how) {
        !          2036:                 case TARGET_SIG_BLOCK:
        !          2037:                     how = SIG_BLOCK;
        !          2038:                     break;
        !          2039:                 case TARGET_SIG_UNBLOCK:
        !          2040:                     how = SIG_UNBLOCK;
        !          2041:                     break;
        !          2042:                 case TARGET_SIG_SETMASK:
        !          2043:                     how = SIG_SETMASK;
        !          2044:                     break;
        !          2045:                 default:
        !          2046:                     ret = -EINVAL;
        !          2047:                     goto fail;
        !          2048:                 }
        !          2049:                 target_to_host_sigset(&set, pset);
        !          2050:                 set_ptr = &set;
        !          2051:             } else {
        !          2052:                 how = 0;
        !          2053:                 set_ptr = NULL;
        !          2054:             }
        !          2055:             ret = get_errno(sigprocmask(how, set_ptr, &oldset));
        !          2056:             if (!is_error(ret) && poldset) {
        !          2057:                 host_to_target_sigset(poldset, &oldset);
        !          2058:             }
        !          2059:         }
        !          2060:         break;
        !          2061:     case TARGET_NR_sigpending:
        !          2062:         {
        !          2063:             sigset_t set;
        !          2064:             ret = get_errno(sigpending(&set));
        !          2065:             if (!is_error(ret)) {
        !          2066:                 host_to_target_old_sigset((target_ulong *)arg1, &set);
        !          2067:             }
        !          2068:         }
        !          2069:         break;
        !          2070:     case TARGET_NR_rt_sigpending:
        !          2071:         {
        !          2072:             sigset_t set;
        !          2073:             ret = get_errno(sigpending(&set));
        !          2074:             if (!is_error(ret)) {
        !          2075:                 host_to_target_sigset((target_sigset_t *)arg1, &set);
        !          2076:             }
        !          2077:         }
        !          2078:         break;
        !          2079:     case TARGET_NR_sigsuspend:
        !          2080:         {
        !          2081:             sigset_t set;
        !          2082:             target_to_host_old_sigset(&set, (target_ulong *)arg1);
        !          2083:             ret = get_errno(sigsuspend(&set));
        !          2084:         }
        !          2085:         break;
        !          2086:     case TARGET_NR_rt_sigsuspend:
        !          2087:         {
        !          2088:             sigset_t set;
        !          2089:             target_to_host_sigset(&set, (target_sigset_t *)arg1);
        !          2090:             ret = get_errno(sigsuspend(&set));
        !          2091:         }
        !          2092:         break;
        !          2093:     case TARGET_NR_rt_sigtimedwait:
        !          2094:         {
        !          2095:             target_sigset_t *target_set = (void *)arg1;
        !          2096:             target_siginfo_t *target_uinfo = (void *)arg2;
        !          2097:             struct target_timespec *target_uts = (void *)arg3;
        !          2098:             sigset_t set;
        !          2099:             struct timespec uts, *puts;
        !          2100:             siginfo_t uinfo;
        !          2101:             
        !          2102:             target_to_host_sigset(&set, target_set);
        !          2103:             if (target_uts) {
        !          2104:                 puts = &uts;
        !          2105:                 puts->tv_sec = tswapl(target_uts->tv_sec);
        !          2106:                 puts->tv_nsec = tswapl(target_uts->tv_nsec);
        !          2107:             } else {
        !          2108:                 puts = NULL;
        !          2109:             }
        !          2110:             ret = get_errno(sigtimedwait(&set, &uinfo, puts));
        !          2111:             if (!is_error(ret) && target_uinfo) {
        !          2112:                 host_to_target_siginfo(target_uinfo, &uinfo);
        !          2113:             }
        !          2114:         }
        !          2115:         break;
        !          2116:     case TARGET_NR_rt_sigqueueinfo:
        !          2117:         {
        !          2118:             siginfo_t uinfo;
        !          2119:             target_to_host_siginfo(&uinfo, (target_siginfo_t *)arg3);
        !          2120:             ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
        !          2121:         }
        !          2122:         break;
        !          2123:     case TARGET_NR_sigreturn:
        !          2124:         /* NOTE: ret is eax, so not transcoding must be done */
        !          2125:         ret = do_sigreturn(cpu_env);
        !          2126:         break;
        !          2127:     case TARGET_NR_rt_sigreturn:
        !          2128:         /* NOTE: ret is eax, so not transcoding must be done */
        !          2129:         ret = do_rt_sigreturn(cpu_env);
        !          2130:         break;
        !          2131:     case TARGET_NR_sethostname:
        !          2132:         ret = get_errno(sethostname((const char *)arg1, arg2));
        !          2133:         break;
        !          2134:     case TARGET_NR_setrlimit:
        !          2135:         {
        !          2136:             /* XXX: convert resource ? */
        !          2137:             int resource = arg1;
        !          2138:             struct target_rlimit *target_rlim = (void *)arg2;
        !          2139:             struct rlimit rlim;
        !          2140:             rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
        !          2141:             rlim.rlim_max = tswapl(target_rlim->rlim_max);
        !          2142:             ret = get_errno(setrlimit(resource, &rlim));
        !          2143:         }
        !          2144:         break;
        !          2145:     case TARGET_NR_getrlimit:
        !          2146:         {
        !          2147:             /* XXX: convert resource ? */
        !          2148:             int resource = arg1;
        !          2149:             struct target_rlimit *target_rlim = (void *)arg2;
        !          2150:             struct rlimit rlim;
        !          2151:             
        !          2152:             ret = get_errno(getrlimit(resource, &rlim));
        !          2153:             if (!is_error(ret)) {
        !          2154:                 target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
        !          2155:                 target_rlim->rlim_max = tswapl(rlim.rlim_max);
        !          2156:             }
        !          2157:         }
        !          2158:         break;
        !          2159:     case TARGET_NR_getrusage:
        !          2160:         {
        !          2161:             struct rusage rusage;
        !          2162:             struct target_rusage *target_rusage = (void *)arg2;
        !          2163:             ret = get_errno(getrusage(arg1, &rusage));
        !          2164:             if (!is_error(ret)) {
        !          2165:                 host_to_target_rusage(target_rusage, &rusage);
        !          2166:             }
        !          2167:         }
        !          2168:         break;
        !          2169:     case TARGET_NR_gettimeofday:
        !          2170:         {
        !          2171:             struct target_timeval *target_tv = (void *)arg1;
        !          2172:             struct timeval tv;
        !          2173:             ret = get_errno(gettimeofday(&tv, NULL));
        !          2174:             if (!is_error(ret)) {
        !          2175:                 host_to_target_timeval(target_tv, &tv);
        !          2176:             }
        !          2177:         }
        !          2178:         break;
        !          2179:     case TARGET_NR_settimeofday:
        !          2180:         {
        !          2181:             struct target_timeval *target_tv = (void *)arg1;
        !          2182:             struct timeval tv;
        !          2183:             target_to_host_timeval(&tv, target_tv);
        !          2184:             ret = get_errno(settimeofday(&tv, NULL));
        !          2185:         }
        !          2186:         break;
        !          2187:     case TARGET_NR_select:
        !          2188:         {
        !          2189:             struct target_sel_arg_struct *sel = (void *)arg1;
        !          2190:             sel->n = tswapl(sel->n);
        !          2191:             sel->inp = tswapl(sel->inp);
        !          2192:             sel->outp = tswapl(sel->outp);
        !          2193:             sel->exp = tswapl(sel->exp);
        !          2194:             sel->tvp = tswapl(sel->tvp);
        !          2195:             ret = do_select(sel->n, (void *)sel->inp, (void *)sel->outp,
        !          2196:                             (void *)sel->exp, (void *)sel->tvp);
        !          2197:         }
        !          2198:         break;
        !          2199:     case TARGET_NR_symlink:
        !          2200:         ret = get_errno(symlink((const char *)arg1, (const char *)arg2));
        !          2201:         break;
        !          2202: #ifdef TARGET_NR_oldlstat
        !          2203:     case TARGET_NR_oldlstat:
        !          2204:         goto unimplemented;
        !          2205: #endif
        !          2206:     case TARGET_NR_readlink:
        !          2207:         ret = get_errno(readlink(path((const char *)arg1), (char *)arg2, arg3));
        !          2208:         break;
        !          2209:     case TARGET_NR_uselib:
        !          2210:         goto unimplemented;
        !          2211:     case TARGET_NR_swapon:
        !          2212:         ret = get_errno(swapon((const char *)arg1, arg2));
        !          2213:         break;
        !          2214:     case TARGET_NR_reboot:
        !          2215:         goto unimplemented;
        !          2216:     case TARGET_NR_readdir:
        !          2217:         goto unimplemented;
        !          2218:     case TARGET_NR_mmap:
        !          2219: #if defined(TARGET_I386) || defined(TARGET_ARM)
        !          2220:         {
        !          2221:             uint32_t v1, v2, v3, v4, v5, v6, *vptr;
        !          2222:             vptr = (uint32_t *)arg1;
        !          2223:             v1 = tswap32(vptr[0]);
        !          2224:             v2 = tswap32(vptr[1]);
        !          2225:             v3 = tswap32(vptr[2]);
        !          2226:             v4 = tswap32(vptr[3]);
        !          2227:             v5 = tswap32(vptr[4]);
        !          2228:             v6 = tswap32(vptr[5]);
        !          2229:             ret = get_errno(target_mmap(v1, v2, v3, 
        !          2230:                                         target_to_host_bitmask(v4, mmap_flags_tbl),
        !          2231:                                         v5, v6));
        !          2232:         }
        !          2233: #else
        !          2234:         ret = get_errno(target_mmap(arg1, arg2, arg3, 
        !          2235:                                     target_to_host_bitmask(arg4, mmap_flags_tbl), 
        !          2236:                                     arg5,
        !          2237:                                     arg6));
        !          2238: #endif
        !          2239:         break;
        !          2240: #ifdef TARGET_NR_mmap2
        !          2241:     case TARGET_NR_mmap2:
        !          2242: #if defined(TARGET_SPARC)
        !          2243: #define MMAP_SHIFT 12
        !          2244: #else
        !          2245: #define MMAP_SHIFT TARGET_PAGE_BITS
        !          2246: #endif
        !          2247:         ret = get_errno(target_mmap(arg1, arg2, arg3, 
        !          2248:                                     target_to_host_bitmask(arg4, mmap_flags_tbl), 
        !          2249:                                     arg5,
        !          2250:                                     arg6 << MMAP_SHIFT));
        !          2251:         break;
        !          2252: #endif
        !          2253:     case TARGET_NR_munmap:
        !          2254:         ret = get_errno(target_munmap(arg1, arg2));
        !          2255:         break;
        !          2256:     case TARGET_NR_mprotect:
        !          2257:         ret = get_errno(target_mprotect(arg1, arg2, arg3));
        !          2258:         break;
        !          2259:     case TARGET_NR_mremap:
        !          2260:         ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
        !          2261:         break;
        !          2262:     case TARGET_NR_msync:
        !          2263:         ret = get_errno(msync((void *)arg1, arg2, arg3));
        !          2264:         break;
        !          2265:     case TARGET_NR_mlock:
        !          2266:         ret = get_errno(mlock((void *)arg1, arg2));
        !          2267:         break;
        !          2268:     case TARGET_NR_munlock:
        !          2269:         ret = get_errno(munlock((void *)arg1, arg2));
        !          2270:         break;
        !          2271:     case TARGET_NR_mlockall:
        !          2272:         ret = get_errno(mlockall(arg1));
        !          2273:         break;
        !          2274:     case TARGET_NR_munlockall:
        !          2275:         ret = get_errno(munlockall());
        !          2276:         break;
        !          2277:     case TARGET_NR_truncate:
        !          2278:         ret = get_errno(truncate((const char *)arg1, arg2));
        !          2279:         break;
        !          2280:     case TARGET_NR_ftruncate:
        !          2281:         ret = get_errno(ftruncate(arg1, arg2));
        !          2282:         break;
        !          2283:     case TARGET_NR_fchmod:
        !          2284:         ret = get_errno(fchmod(arg1, arg2));
        !          2285:         break;
        !          2286:     case TARGET_NR_getpriority:
        !          2287:         ret = get_errno(getpriority(arg1, arg2));
        !          2288:         break;
        !          2289:     case TARGET_NR_setpriority:
        !          2290:         ret = get_errno(setpriority(arg1, arg2, arg3));
        !          2291:         break;
        !          2292: #ifdef TARGET_NR_profil
        !          2293:     case TARGET_NR_profil:
        !          2294:         goto unimplemented;
        !          2295: #endif
        !          2296:     case TARGET_NR_statfs:
        !          2297:         stfs = (void *)arg2;
        !          2298:         ret = get_errno(sys_statfs(path((const char *)arg1), stfs));
        !          2299:     convert_statfs:
        !          2300:         if (!is_error(ret)) {
        !          2301:             tswap32s(&stfs->f_type);
        !          2302:             tswap32s(&stfs->f_bsize);
        !          2303:             tswap32s(&stfs->f_blocks);
        !          2304:             tswap32s(&stfs->f_bfree);
        !          2305:             tswap32s(&stfs->f_bavail);
        !          2306:             tswap32s(&stfs->f_files);
        !          2307:             tswap32s(&stfs->f_ffree);
        !          2308:             tswap32s(&stfs->f_fsid.val[0]);
        !          2309:             tswap32s(&stfs->f_fsid.val[1]);
        !          2310:             tswap32s(&stfs->f_namelen);
        !          2311:         }
        !          2312:         break;
        !          2313:     case TARGET_NR_fstatfs:
        !          2314:         stfs = (void *)arg2;
        !          2315:         ret = get_errno(sys_fstatfs(arg1, stfs));
        !          2316:         goto convert_statfs;
        !          2317: #ifdef TARGET_NR_ioperm
        !          2318:     case TARGET_NR_ioperm:
        !          2319:         goto unimplemented;
        !          2320: #endif
        !          2321:     case TARGET_NR_socketcall:
        !          2322:         ret = do_socketcall(arg1, (int32_t *)arg2);
        !          2323:         break;
        !          2324:     case TARGET_NR_syslog:
        !          2325:         goto unimplemented;
        !          2326:     case TARGET_NR_setitimer:
        !          2327:         {
        !          2328:             struct target_itimerval *target_value = (void *)arg2;
        !          2329:             struct target_itimerval *target_ovalue = (void *)arg3;
        !          2330:             struct itimerval value, ovalue, *pvalue;
        !          2331: 
        !          2332:             if (target_value) {
        !          2333:                 pvalue = &value;
        !          2334:                 target_to_host_timeval(&pvalue->it_interval, 
        !          2335:                                        &target_value->it_interval);
        !          2336:                 target_to_host_timeval(&pvalue->it_value, 
        !          2337:                                        &target_value->it_value);
        !          2338:             } else {
        !          2339:                 pvalue = NULL;
        !          2340:             }
        !          2341:             ret = get_errno(setitimer(arg1, pvalue, &ovalue));
        !          2342:             if (!is_error(ret) && target_ovalue) {
        !          2343:                 host_to_target_timeval(&target_ovalue->it_interval, 
        !          2344:                                        &ovalue.it_interval);
        !          2345:                 host_to_target_timeval(&target_ovalue->it_value, 
        !          2346:                                        &ovalue.it_value);
        !          2347:             }
        !          2348:         }
        !          2349:         break;
        !          2350:     case TARGET_NR_getitimer:
        !          2351:         {
        !          2352:             struct target_itimerval *target_value = (void *)arg2;
        !          2353:             struct itimerval value;
        !          2354:             
        !          2355:             ret = get_errno(getitimer(arg1, &value));
        !          2356:             if (!is_error(ret) && target_value) {
        !          2357:                 host_to_target_timeval(&target_value->it_interval, 
        !          2358:                                        &value.it_interval);
        !          2359:                 host_to_target_timeval(&target_value->it_value, 
        !          2360:                                        &value.it_value);
        !          2361:             }
        !          2362:         }
        !          2363:         break;
        !          2364:     case TARGET_NR_stat:
        !          2365:         ret = get_errno(stat(path((const char *)arg1), &st));
        !          2366:         goto do_stat;
        !          2367:     case TARGET_NR_lstat:
        !          2368:         ret = get_errno(lstat(path((const char *)arg1), &st));
        !          2369:         goto do_stat;
        !          2370:     case TARGET_NR_fstat:
        !          2371:         {
        !          2372:             ret = get_errno(fstat(arg1, &st));
        !          2373:         do_stat:
        !          2374:             if (!is_error(ret)) {
        !          2375:                 struct target_stat *target_st = (void *)arg2;
        !          2376:                 target_st->st_dev = tswap16(st.st_dev);
        !          2377:                 target_st->st_ino = tswapl(st.st_ino);
        !          2378: #if defined(TARGET_PPC)
        !          2379:                 target_st->st_mode = tswapl(st.st_mode); /* XXX: check this */
        !          2380:                 target_st->st_uid = tswap32(st.st_uid);
        !          2381:                 target_st->st_gid = tswap32(st.st_gid);
        !          2382: #else
        !          2383:                 target_st->st_mode = tswap16(st.st_mode);
        !          2384:                 target_st->st_uid = tswap16(st.st_uid);
        !          2385:                 target_st->st_gid = tswap16(st.st_gid);
        !          2386: #endif
        !          2387:                 target_st->st_nlink = tswap16(st.st_nlink);
        !          2388:                 target_st->st_rdev = tswap16(st.st_rdev);
        !          2389:                 target_st->st_size = tswapl(st.st_size);
        !          2390:                 target_st->st_blksize = tswapl(st.st_blksize);
        !          2391:                 target_st->st_blocks = tswapl(st.st_blocks);
        !          2392:                 target_st->target_st_atime = tswapl(st.st_atime);
        !          2393:                 target_st->target_st_mtime = tswapl(st.st_mtime);
        !          2394:                 target_st->target_st_ctime = tswapl(st.st_ctime);
        !          2395:             }
        !          2396:         }
        !          2397:         break;
        !          2398: #ifdef TARGET_NR_olduname
        !          2399:     case TARGET_NR_olduname:
        !          2400:         goto unimplemented;
        !          2401: #endif
        !          2402: #ifdef TARGET_NR_iopl
        !          2403:     case TARGET_NR_iopl:
        !          2404:         goto unimplemented;
        !          2405: #endif
        !          2406:     case TARGET_NR_vhangup:
        !          2407:         ret = get_errno(vhangup());
        !          2408:         break;
        !          2409: #ifdef TARGET_NR_idle
        !          2410:     case TARGET_NR_idle:
        !          2411:         goto unimplemented;
        !          2412: #endif
        !          2413: #ifdef TARGET_NR_syscall
        !          2414:     case TARGET_NR_syscall:
        !          2415:        ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
        !          2416:        break;
        !          2417: #endif
        !          2418:     case TARGET_NR_wait4:
        !          2419:         {
        !          2420:             int status;
        !          2421:             target_long *status_ptr = (void *)arg2;
        !          2422:             struct rusage rusage, *rusage_ptr;
        !          2423:             struct target_rusage *target_rusage = (void *)arg4;
        !          2424:             if (target_rusage)
        !          2425:                 rusage_ptr = &rusage;
        !          2426:             else
        !          2427:                 rusage_ptr = NULL;
        !          2428:             ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
        !          2429:             if (!is_error(ret)) {
        !          2430:                 if (status_ptr)
        !          2431:                     *status_ptr = tswap32(status);
        !          2432:                 if (target_rusage) {
        !          2433:                     host_to_target_rusage(target_rusage, &rusage);
        !          2434:                 }
        !          2435:             }
        !          2436:         }
        !          2437:         break;
        !          2438:     case TARGET_NR_swapoff:
        !          2439:         ret = get_errno(swapoff((const char *)arg1));
        !          2440:         break;
        !          2441:     case TARGET_NR_sysinfo:
        !          2442:         {
        !          2443:             struct target_sysinfo *target_value = (void *)arg1;
        !          2444:             struct sysinfo value;
        !          2445:             ret = get_errno(sysinfo(&value));
        !          2446:             if (!is_error(ret) && target_value)
        !          2447:             {
        !          2448:                 __put_user(value.uptime, &target_value->uptime);
        !          2449:                 __put_user(value.loads[0], &target_value->loads[0]);
        !          2450:                 __put_user(value.loads[1], &target_value->loads[1]);
        !          2451:                 __put_user(value.loads[2], &target_value->loads[2]);
        !          2452:                 __put_user(value.totalram, &target_value->totalram);
        !          2453:                 __put_user(value.freeram, &target_value->freeram);
        !          2454:                 __put_user(value.sharedram, &target_value->sharedram);
        !          2455:                 __put_user(value.bufferram, &target_value->bufferram);
        !          2456:                 __put_user(value.totalswap, &target_value->totalswap);
        !          2457:                 __put_user(value.freeswap, &target_value->freeswap);
        !          2458:                 __put_user(value.procs, &target_value->procs);
        !          2459:                 __put_user(value.totalhigh, &target_value->totalhigh);
        !          2460:                 __put_user(value.freehigh, &target_value->freehigh);
        !          2461:                 __put_user(value.mem_unit, &target_value->mem_unit);
        !          2462:             }
        !          2463:         }
        !          2464:         break;
        !          2465:     case TARGET_NR_ipc:
        !          2466:        ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
        !          2467:        break;
        !          2468:     case TARGET_NR_fsync:
        !          2469:         ret = get_errno(fsync(arg1));
        !          2470:         break;
        !          2471:     case TARGET_NR_clone:
        !          2472:         ret = get_errno(do_fork(cpu_env, arg1, arg2));
        !          2473:         break;
        !          2474: #ifdef __NR_exit_group
        !          2475:         /* new thread calls */
        !          2476:     case TARGET_NR_exit_group:
        !          2477:         gdb_exit(cpu_env, arg1);
        !          2478:         ret = get_errno(exit_group(arg1));
        !          2479:         break;
        !          2480: #endif
        !          2481:     case TARGET_NR_setdomainname:
        !          2482:         ret = get_errno(setdomainname((const char *)arg1, arg2));
        !          2483:         break;
        !          2484:     case TARGET_NR_uname:
        !          2485:         /* no need to transcode because we use the linux syscall */
        !          2486:         {
        !          2487:             struct new_utsname * buf;
        !          2488:     
        !          2489:             buf = (struct new_utsname *)arg1;
        !          2490:             ret = get_errno(sys_uname(buf));
        !          2491:             if (!is_error(ret)) {
        !          2492:                 /* Overrite the native machine name with whatever is being
        !          2493:                    emulated. */
        !          2494:                 strcpy (buf->machine, UNAME_MACHINE);
        !          2495:             }
        !          2496:         }
        !          2497:         break;
        !          2498: #ifdef TARGET_I386
        !          2499:     case TARGET_NR_modify_ldt:
        !          2500:         ret = get_errno(do_modify_ldt(cpu_env, arg1, (void *)arg2, arg3));
        !          2501:         break;
        !          2502:     case TARGET_NR_vm86old:
        !          2503:         goto unimplemented;
        !          2504:     case TARGET_NR_vm86:
        !          2505:         ret = do_vm86(cpu_env, arg1, (void *)arg2);
        !          2506:         break;
        !          2507: #endif
        !          2508:     case TARGET_NR_adjtimex:
        !          2509:         goto unimplemented;
        !          2510:     case TARGET_NR_create_module:
        !          2511:     case TARGET_NR_init_module:
        !          2512:     case TARGET_NR_delete_module:
        !          2513:     case TARGET_NR_get_kernel_syms:
        !          2514:         goto unimplemented;
        !          2515:     case TARGET_NR_quotactl:
        !          2516:         goto unimplemented;
        !          2517:     case TARGET_NR_getpgid:
        !          2518:         ret = get_errno(getpgid(arg1));
        !          2519:         break;
        !          2520:     case TARGET_NR_fchdir:
        !          2521:         ret = get_errno(fchdir(arg1));
        !          2522:         break;
        !          2523:     case TARGET_NR_bdflush:
        !          2524:         goto unimplemented;
        !          2525:     case TARGET_NR_sysfs:
        !          2526:         goto unimplemented;
        !          2527:     case TARGET_NR_personality:
        !          2528:         ret = get_errno(personality(arg1));
        !          2529:         break;
        !          2530:     case TARGET_NR_afs_syscall:
        !          2531:         goto unimplemented;
        !          2532:     case TARGET_NR__llseek:
        !          2533:         {
        !          2534: #if defined (__x86_64__)
        !          2535:             ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
        !          2536:             *(int64_t *)arg4 = ret;
        !          2537: #else
        !          2538:             int64_t res;
        !          2539:             ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
        !          2540:             *(int64_t *)arg4 = tswap64(res);
        !          2541: #endif
        !          2542:         }
        !          2543:         break;
        !          2544:     case TARGET_NR_getdents:
        !          2545: #if TARGET_LONG_SIZE != 4
        !          2546: #warning not supported
        !          2547: #elif TARGET_LONG_SIZE == 4 && HOST_LONG_SIZE == 8
        !          2548:         {
        !          2549:             struct target_dirent *target_dirp = (void *)arg2;
        !          2550:             struct dirent *dirp;
        !          2551:             long count = arg3;
        !          2552: 
        !          2553:            dirp = malloc(count);
        !          2554:            if (!dirp)
        !          2555:                 return -ENOMEM;
        !          2556:             
        !          2557:             ret = get_errno(sys_getdents(arg1, dirp, count));
        !          2558:             if (!is_error(ret)) {
        !          2559:                 struct dirent *de;
        !          2560:                struct target_dirent *tde;
        !          2561:                 int len = ret;
        !          2562:                 int reclen, treclen;
        !          2563:                int count1, tnamelen;
        !          2564: 
        !          2565:                count1 = 0;
        !          2566:                 de = dirp;
        !          2567:                tde = target_dirp;
        !          2568:                 while (len > 0) {
        !          2569:                     reclen = de->d_reclen;
        !          2570:                    treclen = reclen - (2 * (sizeof(long) - sizeof(target_long)));
        !          2571:                     tde->d_reclen = tswap16(treclen);
        !          2572:                     tde->d_ino = tswapl(de->d_ino);
        !          2573:                     tde->d_off = tswapl(de->d_off);
        !          2574:                    tnamelen = treclen - (2 * sizeof(target_long) + 2);
        !          2575:                    if (tnamelen > 256)
        !          2576:                         tnamelen = 256;
        !          2577:                     /* XXX: may not be correct */
        !          2578:                    strncpy(tde->d_name, de->d_name, tnamelen);
        !          2579:                     de = (struct dirent *)((char *)de + reclen);
        !          2580:                     len -= reclen;
        !          2581:                     tde = (struct dirent *)((char *)tde + treclen);
        !          2582:                    count1 += treclen;
        !          2583:                 }
        !          2584:                ret = count1;
        !          2585:             }
        !          2586:            free(dirp);
        !          2587:         }
        !          2588: #else
        !          2589:         {
        !          2590:             struct dirent *dirp = (void *)arg2;
        !          2591:             long count = arg3;
        !          2592: 
        !          2593:             ret = get_errno(sys_getdents(arg1, dirp, count));
        !          2594:             if (!is_error(ret)) {
        !          2595:                 struct dirent *de;
        !          2596:                 int len = ret;
        !          2597:                 int reclen;
        !          2598:                 de = dirp;
        !          2599:                 while (len > 0) {
        !          2600:                     reclen = de->d_reclen;
        !          2601:                     if (reclen > len)
        !          2602:                         break;
        !          2603:                     de->d_reclen = tswap16(reclen);
        !          2604:                     tswapls(&de->d_ino);
        !          2605:                     tswapls(&de->d_off);
        !          2606:                     de = (struct dirent *)((char *)de + reclen);
        !          2607:                     len -= reclen;
        !          2608:                 }
        !          2609:             }
        !          2610:         }
        !          2611: #endif
        !          2612:         break;
        !          2613: #ifdef TARGET_NR_getdents64
        !          2614:     case TARGET_NR_getdents64:
        !          2615:         {
        !          2616:             struct dirent64 *dirp = (void *)arg2;
        !          2617:             long count = arg3;
        !          2618:             ret = get_errno(sys_getdents64(arg1, dirp, count));
        !          2619:             if (!is_error(ret)) {
        !          2620:                 struct dirent64 *de;
        !          2621:                 int len = ret;
        !          2622:                 int reclen;
        !          2623:                 de = dirp;
        !          2624:                 while (len > 0) {
        !          2625:                     reclen = de->d_reclen;
        !          2626:                     if (reclen > len)
        !          2627:                         break;
        !          2628:                     de->d_reclen = tswap16(reclen);
        !          2629:                     tswap64s(&de->d_ino);
        !          2630:                     tswap64s(&de->d_off);
        !          2631:                     de = (struct dirent64 *)((char *)de + reclen);
        !          2632:                     len -= reclen;
        !          2633:                 }
        !          2634:             }
        !          2635:         }
        !          2636:         break;
        !          2637: #endif /* TARGET_NR_getdents64 */
        !          2638:     case TARGET_NR__newselect:
        !          2639:         ret = do_select(arg1, (void *)arg2, (void *)arg3, (void *)arg4, 
        !          2640:                         (void *)arg5);
        !          2641:         break;
        !          2642:     case TARGET_NR_poll:
        !          2643:         {
        !          2644:             struct target_pollfd *target_pfd = (void *)arg1;
        !          2645:             unsigned int nfds = arg2;
        !          2646:             int timeout = arg3;
        !          2647:             struct pollfd *pfd;
        !          2648:             unsigned int i;
        !          2649: 
        !          2650:             pfd = alloca(sizeof(struct pollfd) * nfds);
        !          2651:             for(i = 0; i < nfds; i++) {
        !          2652:                 pfd[i].fd = tswap32(target_pfd[i].fd);
        !          2653:                 pfd[i].events = tswap16(target_pfd[i].events);
        !          2654:             }
        !          2655:             ret = get_errno(poll(pfd, nfds, timeout));
        !          2656:             if (!is_error(ret)) {
        !          2657:                 for(i = 0; i < nfds; i++) {
        !          2658:                     target_pfd[i].revents = tswap16(pfd[i].revents);
        !          2659:                 }
        !          2660:             }
        !          2661:         }
        !          2662:         break;
        !          2663:     case TARGET_NR_flock:
        !          2664:         /* NOTE: the flock constant seems to be the same for every
        !          2665:            Linux platform */
        !          2666:         ret = get_errno(flock(arg1, arg2));
        !          2667:         break;
        !          2668:     case TARGET_NR_readv:
        !          2669:         {
        !          2670:             int count = arg3;
        !          2671:             int i;
        !          2672:             struct iovec *vec;
        !          2673:             struct target_iovec *target_vec = (void *)arg2;
        !          2674: 
        !          2675:             vec = alloca(count * sizeof(struct iovec));
        !          2676:             for(i = 0;i < count; i++) {
        !          2677:                 vec[i].iov_base = (void *)tswapl(target_vec[i].iov_base);
        !          2678:                 vec[i].iov_len = tswapl(target_vec[i].iov_len);
        !          2679:             }
        !          2680:             ret = get_errno(readv(arg1, vec, count));
        !          2681:         }
        !          2682:         break;
        !          2683:     case TARGET_NR_writev:
        !          2684:         {
        !          2685:             int count = arg3;
        !          2686:             int i;
        !          2687:             struct iovec *vec;
        !          2688:             struct target_iovec *target_vec = (void *)arg2;
        !          2689: 
        !          2690:             vec = alloca(count * sizeof(struct iovec));
        !          2691:             for(i = 0;i < count; i++) {
        !          2692:                 vec[i].iov_base = (void *)tswapl(target_vec[i].iov_base);
        !          2693:                 vec[i].iov_len = tswapl(target_vec[i].iov_len);
        !          2694:             }
        !          2695:             ret = get_errno(writev(arg1, vec, count));
        !          2696:         }
        !          2697:         break;
        !          2698:     case TARGET_NR_getsid:
        !          2699:         ret = get_errno(getsid(arg1));
        !          2700:         break;
        !          2701:     case TARGET_NR_fdatasync:
        !          2702:         ret = get_errno(fdatasync(arg1));
        !          2703:         break;
        !          2704:     case TARGET_NR__sysctl:
        !          2705:         /* We don't implement this, but ENODIR is always a safe
        !          2706:            return value. */
        !          2707:         return -ENOTDIR;
        !          2708:     case TARGET_NR_sched_setparam:
        !          2709:         {
        !          2710:             struct sched_param *target_schp = (void *)arg2;
        !          2711:             struct sched_param schp;
        !          2712:             schp.sched_priority = tswap32(target_schp->sched_priority);
        !          2713:             ret = get_errno(sched_setparam(arg1, &schp));
        !          2714:         }
        !          2715:         break;
        !          2716:     case TARGET_NR_sched_getparam:
        !          2717:         {
        !          2718:             struct sched_param *target_schp = (void *)arg2;
        !          2719:             struct sched_param schp;
        !          2720:             ret = get_errno(sched_getparam(arg1, &schp));
        !          2721:             if (!is_error(ret)) {
        !          2722:                 target_schp->sched_priority = tswap32(schp.sched_priority);
        !          2723:             }
        !          2724:         }
        !          2725:         break;
        !          2726:     case TARGET_NR_sched_setscheduler:
        !          2727:         {
        !          2728:             struct sched_param *target_schp = (void *)arg3;
        !          2729:             struct sched_param schp;
        !          2730:             schp.sched_priority = tswap32(target_schp->sched_priority);
        !          2731:             ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
        !          2732:         }
        !          2733:         break;
        !          2734:     case TARGET_NR_sched_getscheduler:
        !          2735:         ret = get_errno(sched_getscheduler(arg1));
        !          2736:         break;
        !          2737:     case TARGET_NR_sched_yield:
        !          2738:         ret = get_errno(sched_yield());
        !          2739:         break;
        !          2740:     case TARGET_NR_sched_get_priority_max:
        !          2741:         ret = get_errno(sched_get_priority_max(arg1));
        !          2742:         break;
        !          2743:     case TARGET_NR_sched_get_priority_min:
        !          2744:         ret = get_errno(sched_get_priority_min(arg1));
        !          2745:         break;
        !          2746:     case TARGET_NR_sched_rr_get_interval:
        !          2747:         {
        !          2748:             struct target_timespec *target_ts = (void *)arg2;
        !          2749:             struct timespec ts;
        !          2750:             ret = get_errno(sched_rr_get_interval(arg1, &ts));
        !          2751:             if (!is_error(ret)) {
        !          2752:                 target_ts->tv_sec = tswapl(ts.tv_sec);
        !          2753:                 target_ts->tv_nsec = tswapl(ts.tv_nsec);
        !          2754:             }
        !          2755:         }
        !          2756:         break;
        !          2757:     case TARGET_NR_nanosleep:
        !          2758:         {
        !          2759:             struct target_timespec *target_req = (void *)arg1;
        !          2760:             struct target_timespec *target_rem = (void *)arg2;
        !          2761:             struct timespec req, rem;
        !          2762:             req.tv_sec = tswapl(target_req->tv_sec);
        !          2763:             req.tv_nsec = tswapl(target_req->tv_nsec);
        !          2764:             ret = get_errno(nanosleep(&req, &rem));
        !          2765:             if (is_error(ret) && target_rem) {
        !          2766:                 target_rem->tv_sec = tswapl(rem.tv_sec);
        !          2767:                 target_rem->tv_nsec = tswapl(rem.tv_nsec);
        !          2768:             }
        !          2769:         }
        !          2770:         break;
        !          2771:     case TARGET_NR_query_module:
        !          2772:         goto unimplemented;
        !          2773:     case TARGET_NR_nfsservctl:
        !          2774:         goto unimplemented;
        !          2775:     case TARGET_NR_prctl:
        !          2776:         goto unimplemented;
        !          2777: #ifdef TARGET_NR_pread
        !          2778:     case TARGET_NR_pread:
        !          2779:         page_unprotect_range((void *)arg2, arg3);
        !          2780:         ret = get_errno(pread(arg1, (void *)arg2, arg3, arg4));
        !          2781:         break;
        !          2782:     case TARGET_NR_pwrite:
        !          2783:         ret = get_errno(pwrite(arg1, (void *)arg2, arg3, arg4));
        !          2784:         break;
        !          2785: #endif
        !          2786:     case TARGET_NR_getcwd:
        !          2787:         ret = get_errno(sys_getcwd1((char *)arg1, arg2));
        !          2788:         break;
        !          2789:     case TARGET_NR_capget:
        !          2790:         goto unimplemented;
        !          2791:     case TARGET_NR_capset:
        !          2792:         goto unimplemented;
        !          2793:     case TARGET_NR_sigaltstack:
        !          2794:         goto unimplemented;
        !          2795:     case TARGET_NR_sendfile:
        !          2796:         goto unimplemented;
        !          2797: #ifdef TARGET_NR_getpmsg
        !          2798:     case TARGET_NR_getpmsg:
        !          2799:         goto unimplemented;
        !          2800: #endif
        !          2801: #ifdef TARGET_NR_putpmsg
        !          2802:     case TARGET_NR_putpmsg:
        !          2803:         goto unimplemented;
        !          2804: #endif
        !          2805:     case TARGET_NR_vfork:
        !          2806:         ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0));
        !          2807:         break;
        !          2808: #ifdef TARGET_NR_ugetrlimit
        !          2809:     case TARGET_NR_ugetrlimit:
        !          2810:     {
        !          2811:        struct rlimit rlim;
        !          2812:        ret = get_errno(getrlimit(arg1, &rlim));
        !          2813:        if (!is_error(ret)) {
        !          2814:            struct target_rlimit *target_rlim = (void *)arg2;
        !          2815:            target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
        !          2816:            target_rlim->rlim_max = tswapl(rlim.rlim_max);
        !          2817:        }
        !          2818:        break;
        !          2819:     }
        !          2820: #endif
        !          2821: #ifdef TARGET_NR_truncate64
        !          2822:     case TARGET_NR_truncate64:
        !          2823:        ret = get_errno(truncate64((const char *)arg1, arg2));
        !          2824:        break;
        !          2825: #endif
        !          2826: #ifdef TARGET_NR_ftruncate64
        !          2827:     case TARGET_NR_ftruncate64:
        !          2828:        ret = get_errno(ftruncate64(arg1, arg2));
        !          2829:        break;
        !          2830: #endif
        !          2831: #ifdef TARGET_NR_stat64
        !          2832:     case TARGET_NR_stat64:
        !          2833:         ret = get_errno(stat(path((const char *)arg1), &st));
        !          2834:         goto do_stat64;
        !          2835: #endif
        !          2836: #ifdef TARGET_NR_lstat64
        !          2837:     case TARGET_NR_lstat64:
        !          2838:         ret = get_errno(lstat(path((const char *)arg1), &st));
        !          2839:         goto do_stat64;
        !          2840: #endif
        !          2841: #ifdef TARGET_NR_fstat64
        !          2842:     case TARGET_NR_fstat64:
        !          2843:         {
        !          2844:             ret = get_errno(fstat(arg1, &st));
        !          2845:         do_stat64:
        !          2846:             if (!is_error(ret)) {
        !          2847:                 struct target_stat64 *target_st = (void *)arg2;
        !          2848:                 memset(target_st, 0, sizeof(struct target_stat64));
        !          2849:                 put_user(st.st_dev, &target_st->st_dev);
        !          2850:                 put_user(st.st_ino, &target_st->st_ino);
        !          2851: #ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
        !          2852:                 put_user(st.st_ino, &target_st->__st_ino);
        !          2853: #endif
        !          2854:                 put_user(st.st_mode, &target_st->st_mode);
        !          2855:                 put_user(st.st_nlink, &target_st->st_nlink);
        !          2856:                 put_user(st.st_uid, &target_st->st_uid);
        !          2857:                 put_user(st.st_gid, &target_st->st_gid);
        !          2858:                 put_user(st.st_rdev, &target_st->st_rdev);
        !          2859:                 /* XXX: better use of kernel struct */
        !          2860:                 put_user(st.st_size, &target_st->st_size);
        !          2861:                 put_user(st.st_blksize, &target_st->st_blksize);
        !          2862:                 put_user(st.st_blocks, &target_st->st_blocks);
        !          2863:                 put_user(st.st_atime, &target_st->target_st_atime);
        !          2864:                 put_user(st.st_mtime, &target_st->target_st_mtime);
        !          2865:                 put_user(st.st_ctime, &target_st->target_st_ctime);
        !          2866:             }
        !          2867:         }
        !          2868:         break;
        !          2869: #endif
        !          2870: #ifdef USE_UID16
        !          2871:     case TARGET_NR_lchown:
        !          2872:         ret = get_errno(lchown((const char *)arg1, low2highuid(arg2), low2highgid(arg3)));
        !          2873:         break;
        !          2874:     case TARGET_NR_getuid:
        !          2875:         ret = get_errno(high2lowuid(getuid()));
        !          2876:         break;
        !          2877:     case TARGET_NR_getgid:
        !          2878:         ret = get_errno(high2lowgid(getgid()));
        !          2879:         break;
        !          2880:     case TARGET_NR_geteuid:
        !          2881:         ret = get_errno(high2lowuid(geteuid()));
        !          2882:         break;
        !          2883:     case TARGET_NR_getegid:
        !          2884:         ret = get_errno(high2lowgid(getegid()));
        !          2885:         break;
        !          2886:     case TARGET_NR_setreuid:
        !          2887:         ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
        !          2888:         break;
        !          2889:     case TARGET_NR_setregid:
        !          2890:         ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
        !          2891:         break;
        !          2892:     case TARGET_NR_getgroups:
        !          2893:         {
        !          2894:             int gidsetsize = arg1;
        !          2895:             uint16_t *target_grouplist = (void *)arg2;
        !          2896:             gid_t *grouplist;
        !          2897:             int i;
        !          2898: 
        !          2899:             grouplist = alloca(gidsetsize * sizeof(gid_t));
        !          2900:             ret = get_errno(getgroups(gidsetsize, grouplist));
        !          2901:             if (!is_error(ret)) {
        !          2902:                 for(i = 0;i < gidsetsize; i++)
        !          2903:                     target_grouplist[i] = tswap16(grouplist[i]);
        !          2904:             }
        !          2905:         }
        !          2906:         break;
        !          2907:     case TARGET_NR_setgroups:
        !          2908:         {
        !          2909:             int gidsetsize = arg1;
        !          2910:             uint16_t *target_grouplist = (void *)arg2;
        !          2911:             gid_t *grouplist;
        !          2912:             int i;
        !          2913: 
        !          2914:             grouplist = alloca(gidsetsize * sizeof(gid_t));
        !          2915:             for(i = 0;i < gidsetsize; i++)
        !          2916:                 grouplist[i] = tswap16(target_grouplist[i]);
        !          2917:             ret = get_errno(setgroups(gidsetsize, grouplist));
        !          2918:         }
        !          2919:         break;
        !          2920:     case TARGET_NR_fchown:
        !          2921:         ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
        !          2922:         break;
        !          2923: #ifdef TARGET_NR_setresuid
        !          2924:     case TARGET_NR_setresuid:
        !          2925:         ret = get_errno(setresuid(low2highuid(arg1), 
        !          2926:                                   low2highuid(arg2), 
        !          2927:                                   low2highuid(arg3)));
        !          2928:         break;
        !          2929: #endif
        !          2930: #ifdef TARGET_NR_getresuid
        !          2931:     case TARGET_NR_getresuid:
        !          2932:         {
        !          2933:             int ruid, euid, suid;
        !          2934:             ret = get_errno(getresuid(&ruid, &euid, &suid));
        !          2935:             if (!is_error(ret)) {
        !          2936:                 *(uint16_t *)arg1 = tswap16(high2lowuid(ruid));
        !          2937:                 *(uint16_t *)arg2 = tswap16(high2lowuid(euid));
        !          2938:                 *(uint16_t *)arg3 = tswap16(high2lowuid(suid));
        !          2939:             }
        !          2940:         }
        !          2941:         break;
        !          2942: #endif
        !          2943: #ifdef TARGET_NR_getresgid
        !          2944:     case TARGET_NR_setresgid:
        !          2945:         ret = get_errno(setresgid(low2highgid(arg1), 
        !          2946:                                   low2highgid(arg2), 
        !          2947:                                   low2highgid(arg3)));
        !          2948:         break;
        !          2949: #endif
        !          2950: #ifdef TARGET_NR_getresgid
        !          2951:     case TARGET_NR_getresgid:
        !          2952:         {
        !          2953:             int rgid, egid, sgid;
        !          2954:             ret = get_errno(getresgid(&rgid, &egid, &sgid));
        !          2955:             if (!is_error(ret)) {
        !          2956:                 *(uint16_t *)arg1 = tswap16(high2lowgid(rgid));
        !          2957:                 *(uint16_t *)arg2 = tswap16(high2lowgid(egid));
        !          2958:                 *(uint16_t *)arg3 = tswap16(high2lowgid(sgid));
        !          2959:             }
        !          2960:         }
        !          2961:         break;
        !          2962: #endif
        !          2963:     case TARGET_NR_chown:
        !          2964:         ret = get_errno(chown((const char *)arg1, low2highuid(arg2), low2highgid(arg3)));
        !          2965:         break;
        !          2966:     case TARGET_NR_setuid:
        !          2967:         ret = get_errno(setuid(low2highuid(arg1)));
        !          2968:         break;
        !          2969:     case TARGET_NR_setgid:
        !          2970:         ret = get_errno(setgid(low2highgid(arg1)));
        !          2971:         break;
        !          2972:     case TARGET_NR_setfsuid:
        !          2973:         ret = get_errno(setfsuid(arg1));
        !          2974:         break;
        !          2975:     case TARGET_NR_setfsgid:
        !          2976:         ret = get_errno(setfsgid(arg1));
        !          2977:         break;
        !          2978: #endif /* USE_UID16 */
        !          2979: 
        !          2980: #ifdef TARGET_NR_lchown32
        !          2981:     case TARGET_NR_lchown32:
        !          2982:         ret = get_errno(lchown((const char *)arg1, arg2, arg3));
        !          2983:         break;
        !          2984: #endif
        !          2985: #ifdef TARGET_NR_getuid32
        !          2986:     case TARGET_NR_getuid32:
        !          2987:         ret = get_errno(getuid());
        !          2988:         break;
        !          2989: #endif
        !          2990: #ifdef TARGET_NR_getgid32
        !          2991:     case TARGET_NR_getgid32:
        !          2992:         ret = get_errno(getgid());
        !          2993:         break;
        !          2994: #endif
        !          2995: #ifdef TARGET_NR_geteuid32
        !          2996:     case TARGET_NR_geteuid32:
        !          2997:         ret = get_errno(geteuid());
        !          2998:         break;
        !          2999: #endif
        !          3000: #ifdef TARGET_NR_getegid32
        !          3001:     case TARGET_NR_getegid32:
        !          3002:         ret = get_errno(getegid());
        !          3003:         break;
        !          3004: #endif
        !          3005: #ifdef TARGET_NR_setreuid32
        !          3006:     case TARGET_NR_setreuid32:
        !          3007:         ret = get_errno(setreuid(arg1, arg2));
        !          3008:         break;
        !          3009: #endif
        !          3010: #ifdef TARGET_NR_setregid32
        !          3011:     case TARGET_NR_setregid32:
        !          3012:         ret = get_errno(setregid(arg1, arg2));
        !          3013:         break;
        !          3014: #endif
        !          3015: #ifdef TARGET_NR_getgroups32
        !          3016:     case TARGET_NR_getgroups32:
        !          3017:         {
        !          3018:             int gidsetsize = arg1;
        !          3019:             uint32_t *target_grouplist = (void *)arg2;
        !          3020:             gid_t *grouplist;
        !          3021:             int i;
        !          3022: 
        !          3023:             grouplist = alloca(gidsetsize * sizeof(gid_t));
        !          3024:             ret = get_errno(getgroups(gidsetsize, grouplist));
        !          3025:             if (!is_error(ret)) {
        !          3026:                 for(i = 0;i < gidsetsize; i++)
        !          3027:                     put_user(grouplist[i], &target_grouplist[i]);
        !          3028:             }
        !          3029:         }
        !          3030:         break;
        !          3031: #endif
        !          3032: #ifdef TARGET_NR_setgroups32
        !          3033:     case TARGET_NR_setgroups32:
        !          3034:         {
        !          3035:             int gidsetsize = arg1;
        !          3036:             uint32_t *target_grouplist = (void *)arg2;
        !          3037:             gid_t *grouplist;
        !          3038:             int i;
        !          3039:             
        !          3040:             grouplist = alloca(gidsetsize * sizeof(gid_t));
        !          3041:             for(i = 0;i < gidsetsize; i++)
        !          3042:                 get_user(grouplist[i], &target_grouplist[i]);
        !          3043:             ret = get_errno(setgroups(gidsetsize, grouplist));
        !          3044:         }
        !          3045:         break;
        !          3046: #endif
        !          3047: #ifdef TARGET_NR_fchown32
        !          3048:     case TARGET_NR_fchown32:
        !          3049:         ret = get_errno(fchown(arg1, arg2, arg3));
        !          3050:         break;
        !          3051: #endif
        !          3052: #ifdef TARGET_NR_setresuid32
        !          3053:     case TARGET_NR_setresuid32:
        !          3054:         ret = get_errno(setresuid(arg1, arg2, arg3));
        !          3055:         break;
        !          3056: #endif
        !          3057: #ifdef TARGET_NR_getresuid32
        !          3058:     case TARGET_NR_getresuid32:
        !          3059:         {
        !          3060:             int ruid, euid, suid;
        !          3061:             ret = get_errno(getresuid(&ruid, &euid, &suid));
        !          3062:             if (!is_error(ret)) {
        !          3063:                 *(uint32_t *)arg1 = tswap32(ruid);
        !          3064:                 *(uint32_t *)arg2 = tswap32(euid);
        !          3065:                 *(uint32_t *)arg3 = tswap32(suid);
        !          3066:             }
        !          3067:         }
        !          3068:         break;
        !          3069: #endif
        !          3070: #ifdef TARGET_NR_setresgid32
        !          3071:     case TARGET_NR_setresgid32:
        !          3072:         ret = get_errno(setresgid(arg1, arg2, arg3));
        !          3073:         break;
        !          3074: #endif
        !          3075: #ifdef TARGET_NR_getresgid32
        !          3076:     case TARGET_NR_getresgid32:
        !          3077:         {
        !          3078:             int rgid, egid, sgid;
        !          3079:             ret = get_errno(getresgid(&rgid, &egid, &sgid));
        !          3080:             if (!is_error(ret)) {
        !          3081:                 *(uint32_t *)arg1 = tswap32(rgid);
        !          3082:                 *(uint32_t *)arg2 = tswap32(egid);
        !          3083:                 *(uint32_t *)arg3 = tswap32(sgid);
        !          3084:             }
        !          3085:         }
        !          3086:         break;
        !          3087: #endif
        !          3088: #ifdef TARGET_NR_chown32
        !          3089:     case TARGET_NR_chown32:
        !          3090:         ret = get_errno(chown((const char *)arg1, arg2, arg3));
        !          3091:         break;
        !          3092: #endif
        !          3093: #ifdef TARGET_NR_setuid32
        !          3094:     case TARGET_NR_setuid32:
        !          3095:         ret = get_errno(setuid(arg1));
        !          3096:         break;
        !          3097: #endif
        !          3098: #ifdef TARGET_NR_setgid32
        !          3099:     case TARGET_NR_setgid32:
        !          3100:         ret = get_errno(setgid(arg1));
        !          3101:         break;
        !          3102: #endif
        !          3103: #ifdef TARGET_NR_setfsuid32
        !          3104:     case TARGET_NR_setfsuid32:
        !          3105:         ret = get_errno(setfsuid(arg1));
        !          3106:         break;
        !          3107: #endif
        !          3108: #ifdef TARGET_NR_setfsgid32
        !          3109:     case TARGET_NR_setfsgid32:
        !          3110:         ret = get_errno(setfsgid(arg1));
        !          3111:         break;
        !          3112: #endif
        !          3113: 
        !          3114:     case TARGET_NR_pivot_root:
        !          3115:         goto unimplemented;
        !          3116: #ifdef TARGET_NR_mincore
        !          3117:     case TARGET_NR_mincore:
        !          3118:         goto unimplemented;
        !          3119: #endif
        !          3120: #ifdef TARGET_NR_madvise
        !          3121:     case TARGET_NR_madvise:
        !          3122:         goto unimplemented;
        !          3123: #endif
        !          3124: #if TARGET_LONG_BITS == 32
        !          3125:     case TARGET_NR_fcntl64:
        !          3126:     {
        !          3127:        struct flock64 fl;
        !          3128:        struct target_flock64 *target_fl = (void *)arg3;
        !          3129: 
        !          3130:         switch(arg2) {
        !          3131:         case F_GETLK64:
        !          3132:             ret = get_errno(fcntl(arg1, arg2, &fl));
        !          3133:            if (ret == 0) {
        !          3134:                target_fl->l_type = tswap16(fl.l_type);
        !          3135:                target_fl->l_whence = tswap16(fl.l_whence);
        !          3136:                target_fl->l_start = tswap64(fl.l_start);
        !          3137:                target_fl->l_len = tswap64(fl.l_len);
        !          3138:                target_fl->l_pid = tswapl(fl.l_pid);
        !          3139:            }
        !          3140:            break;
        !          3141: 
        !          3142:         case F_SETLK64:
        !          3143:         case F_SETLKW64:
        !          3144:            fl.l_type = tswap16(target_fl->l_type);
        !          3145:            fl.l_whence = tswap16(target_fl->l_whence);
        !          3146:            fl.l_start = tswap64(target_fl->l_start);
        !          3147:            fl.l_len = tswap64(target_fl->l_len);
        !          3148:            fl.l_pid = tswapl(target_fl->l_pid);
        !          3149:             ret = get_errno(fcntl(arg1, arg2, &fl));
        !          3150:            break;
        !          3151:         default:
        !          3152:             ret = get_errno(do_fcntl(arg1, arg2, arg3));
        !          3153:             break;
        !          3154:         }
        !          3155:        break;
        !          3156:     }
        !          3157: #endif
        !          3158: #ifdef TARGET_NR_security
        !          3159:     case TARGET_NR_security:
        !          3160:         goto unimplemented;
        !          3161: #endif
        !          3162: #ifdef TARGET_NR_getpagesize
        !          3163:     case TARGET_NR_getpagesize:
        !          3164:         ret = TARGET_PAGE_SIZE;
        !          3165:         break;
        !          3166: #endif
        !          3167:     case TARGET_NR_gettid:
        !          3168:         ret = get_errno(gettid());
        !          3169:         break;
        !          3170:     case TARGET_NR_readahead:
        !          3171:         goto unimplemented;
        !          3172: #ifdef TARGET_NR_setxattr
        !          3173:     case TARGET_NR_setxattr:
        !          3174:     case TARGET_NR_lsetxattr:
        !          3175:     case TARGET_NR_fsetxattr:
        !          3176:     case TARGET_NR_getxattr:
        !          3177:     case TARGET_NR_lgetxattr:
        !          3178:     case TARGET_NR_fgetxattr:
        !          3179:     case TARGET_NR_listxattr:
        !          3180:     case TARGET_NR_llistxattr:
        !          3181:     case TARGET_NR_flistxattr:
        !          3182:     case TARGET_NR_removexattr:
        !          3183:     case TARGET_NR_lremovexattr:
        !          3184:     case TARGET_NR_fremovexattr:
        !          3185:         goto unimplemented_nowarn;
        !          3186: #endif
        !          3187: #ifdef TARGET_NR_set_thread_area
        !          3188:     case TARGET_NR_set_thread_area:
        !          3189:     case TARGET_NR_get_thread_area:
        !          3190:         goto unimplemented_nowarn;
        !          3191: #endif
        !          3192:     default:
        !          3193:     unimplemented:
        !          3194:         gemu_log("qemu: Unsupported syscall: %d\n", num);
        !          3195: #if defined(TARGET_NR_setxattr) || defined(TARGET_NR_set_thread_area)
        !          3196:     unimplemented_nowarn:
        !          3197: #endif
        !          3198:         ret = -ENOSYS;
        !          3199:         break;
        !          3200:     }
        !          3201:  fail:
        !          3202: #ifdef DEBUG
        !          3203:     gemu_log(" = %ld\n", ret);
        !          3204: #endif
        !          3205:     return ret;
        !          3206: }
        !          3207: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.