|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.