X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=linux-user%2Fsyscall.c;h=1204a62c439809ab8ae9debebbdefa4cd4cb1571;hb=3802ce26a1b60fe791aee1ff3e15ab6dc0bdac27;hp=3f6084d055d4f260c5b3540a903efb020fc1bc7d;hpb=19b84f3c35d7c8e9d4743cdeb93534f7640001e1;p=qemu diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 3f6084d..1204a62 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -64,20 +64,10 @@ //#define DEBUG -#ifndef PAGE_SIZE -#define PAGE_SIZE 4096 -#define PAGE_MASK ~(PAGE_SIZE - 1) -#endif - //#include #define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) #define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2]) -void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info); -void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo); -long do_sigreturn(CPUX86State *env); -long do_rt_sigreturn(CPUX86State *env); - #define __NR_sys_uname __NR_uname #define __NR_sys_getcwd1 __NR_getcwd #define __NR_sys_statfs __NR_statfs @@ -153,7 +143,7 @@ static long do_brk(char *new_brk) if (new_brk < target_original_brk) return -ENOMEM; - brk_page = (char *)(((unsigned long)target_brk + PAGE_SIZE - 1) & PAGE_MASK); + brk_page = (char *)HOST_PAGE_ALIGN((unsigned long)target_brk); /* If the new brk is less than this, set it and we're done... */ if (new_brk < brk_page) { @@ -162,11 +152,10 @@ static long do_brk(char *new_brk) } /* We need to allocate more memory after the brk... */ - new_alloc_size = ((new_brk - brk_page + 1)+(PAGE_SIZE-1)) & PAGE_MASK; - mapped_addr = get_errno((long)mmap((caddr_t)brk_page, new_alloc_size, - PROT_READ|PROT_WRITE, - MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0)); - + new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1); + mapped_addr = get_errno(target_mmap((unsigned long)brk_page, new_alloc_size, + PROT_READ|PROT_WRITE, + MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0)); if (is_error(mapped_addr)) { return mapped_addr; } else { @@ -221,6 +210,44 @@ static inline void host_to_target_fds(target_long *target_fds, #endif } +#if defined(__alpha__) +#define HOST_HZ 1024 +#else +#define HOST_HZ 100 +#endif + +static inline long host_to_target_clock_t(long ticks) +{ +#if HOST_HZ == TARGET_HZ + return ticks; +#else + return ((int64_t)ticks * TARGET_HZ) / HOST_HZ; +#endif +} + +static inline void host_to_target_rusage(struct target_rusage *target_rusage, + const struct rusage *rusage) +{ + target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec); + target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec); + target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec); + target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec); + target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss); + target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss); + target_rusage->ru_idrss = tswapl(rusage->ru_idrss); + target_rusage->ru_isrss = tswapl(rusage->ru_isrss); + target_rusage->ru_minflt = tswapl(rusage->ru_minflt); + target_rusage->ru_majflt = tswapl(rusage->ru_majflt); + target_rusage->ru_nswap = tswapl(rusage->ru_nswap); + target_rusage->ru_inblock = tswapl(rusage->ru_inblock); + target_rusage->ru_oublock = tswapl(rusage->ru_oublock); + target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd); + target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv); + target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals); + target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw); + target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw); +} + static inline void target_to_host_timeval(struct timeval *tv, const struct target_timeval *target_tv) { @@ -685,8 +712,8 @@ enum { #undef STRUCT_SPECIAL typedef struct IOCTLEntry { - int target_cmd; - int host_cmd; + unsigned int target_cmd; + unsigned int host_cmd; const char *name; int access; const argtype arg_type[5]; @@ -698,7 +725,7 @@ typedef struct IOCTLEntry { #define MAX_STRUCT_SIZE 4096 -const IOCTLEntry ioctl_entries[] = { +IOCTLEntry ioctl_entries[] = { #define IOCTL(cmd, access, types...) \ { TARGET_ ## cmd, cmd, #cmd, access, { types } }, #include "ioctls.h" @@ -941,7 +968,19 @@ StructEntry struct_termios_def = { .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) }, }; -#ifdef TARGET_I386 +static bitmask_transtbl mmap_flags_tbl[] = { + { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED }, + { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE }, + { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED }, + { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS }, + { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN }, + { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE }, + { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE }, + { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED }, + { 0, 0, 0, 0 } +}; + +#if defined(TARGET_I386) /* NOTE: there is really one LDT for all the threads */ uint8_t *ldt_table; @@ -1030,7 +1069,7 @@ static int write_ldt(CPUX86State *env, 0x7000; if (!oldmode) entry_2 |= (useable << 20); - + /* Install the new entry ... */ install: lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3)); @@ -1058,77 +1097,7 @@ int do_modify_ldt(CPUX86State *env, int func, void *ptr, unsigned long bytecount return ret; } -/* vm86 emulation */ - -#define SAFE_MASK (0xDD5) - -int do_vm86(CPUX86State *env, long subfunction, - struct target_vm86plus_struct * target_v86) -{ - TaskState *ts = env->opaque; - int ret; - - switch (subfunction) { - case TARGET_VM86_REQUEST_IRQ: - case TARGET_VM86_FREE_IRQ: - case TARGET_VM86_GET_IRQ_BITS: - case TARGET_VM86_GET_AND_RESET_IRQ: - gemu_log("qemu: unsupported vm86 subfunction (%ld)\n", subfunction); - ret = -EINVAL; - goto out; - case TARGET_VM86_PLUS_INSTALL_CHECK: - /* NOTE: on old vm86 stuff this will return the error - from verify_area(), because the subfunction is - interpreted as (invalid) address to vm86_struct. - So the installation check works. - */ - ret = 0; - goto out; - } - - ts->target_v86 = target_v86; - /* save current CPU regs */ - ts->vm86_saved_regs.eax = 0; /* default vm86 syscall return code */ - ts->vm86_saved_regs.ebx = env->regs[R_EBX]; - ts->vm86_saved_regs.ecx = env->regs[R_ECX]; - ts->vm86_saved_regs.edx = env->regs[R_EDX]; - ts->vm86_saved_regs.esi = env->regs[R_ESI]; - ts->vm86_saved_regs.edi = env->regs[R_EDI]; - ts->vm86_saved_regs.ebp = env->regs[R_EBP]; - ts->vm86_saved_regs.esp = env->regs[R_ESP]; - ts->vm86_saved_regs.eflags = env->eflags; - ts->vm86_saved_regs.eip = env->eip; - ts->vm86_saved_regs.cs = env->segs[R_CS]; - ts->vm86_saved_regs.ss = env->segs[R_SS]; - ts->vm86_saved_regs.ds = env->segs[R_DS]; - ts->vm86_saved_regs.es = env->segs[R_ES]; - ts->vm86_saved_regs.fs = env->segs[R_FS]; - ts->vm86_saved_regs.gs = env->segs[R_GS]; - - /* build vm86 CPU state */ - env->eflags = (env->eflags & ~SAFE_MASK) | - (tswap32(target_v86->regs.eflags) & SAFE_MASK) | VM_MASK; - - env->regs[R_EBX] = tswap32(target_v86->regs.ebx); - env->regs[R_ECX] = tswap32(target_v86->regs.ecx); - env->regs[R_EDX] = tswap32(target_v86->regs.edx); - env->regs[R_ESI] = tswap32(target_v86->regs.esi); - env->regs[R_EDI] = tswap32(target_v86->regs.edi); - env->regs[R_EBP] = tswap32(target_v86->regs.ebp); - env->regs[R_ESP] = tswap32(target_v86->regs.esp); - env->eip = tswap32(target_v86->regs.eip); - cpu_x86_load_seg(env, R_CS, tswap16(target_v86->regs.cs)); - cpu_x86_load_seg(env, R_SS, tswap16(target_v86->regs.ss)); - cpu_x86_load_seg(env, R_DS, tswap16(target_v86->regs.ds)); - cpu_x86_load_seg(env, R_ES, tswap16(target_v86->regs.es)); - cpu_x86_load_seg(env, R_FS, tswap16(target_v86->regs.fs)); - cpu_x86_load_seg(env, R_GS, tswap16(target_v86->regs.gs)); - ret = tswap32(target_v86->regs.eax); /* eax will be restored at - the end of the syscall */ - /* now the virtual CPU is ready for vm86 execution ! */ - out: - return ret; -} +#endif /* defined(TARGET_I386) */ /* this stack is the equivalent of the kernel stack associated with a thread/process */ @@ -1136,22 +1105,20 @@ int do_vm86(CPUX86State *env, long subfunction, static int clone_func(void *arg) { - CPUX86State *env = arg; + CPUState *env = arg; cpu_loop(env); /* never exits */ return 0; } -int do_fork(CPUX86State *env, unsigned int flags, unsigned long newsp) +int do_fork(CPUState *env, unsigned int flags, unsigned long newsp) { int ret; TaskState *ts; uint8_t *new_stack; - CPUX86State *new_env; + CPUState *new_env; if (flags & CLONE_VM) { - if (!newsp) - newsp = env->regs[R_ESP]; ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE); memset(ts, 0, sizeof(TaskState)); new_stack = ts->stack; @@ -1160,10 +1127,21 @@ int do_fork(CPUX86State *env, unsigned int flags, unsigned long newsp) ts->next = first_task_state; first_task_state = ts; /* we create a new CPU instance. */ - new_env = cpu_x86_init(); - memcpy(new_env, env, sizeof(CPUX86State)); + new_env = cpu_init(); + memcpy(new_env, env, sizeof(CPUState)); +#if defined(TARGET_I386) + if (!newsp) + newsp = env->regs[R_ESP]; new_env->regs[R_ESP] = newsp; new_env->regs[R_EAX] = 0; +#elif defined(TARGET_ARM) + if (!newsp) + newsp = env->regs[13]; + new_env->regs[13] = newsp; + new_env->regs[0] = 0; +#else +#error unsupported target CPU +#endif new_env->opaque = ts; #ifdef __ia64__ ret = clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env); @@ -1179,7 +1157,48 @@ int do_fork(CPUX86State *env, unsigned int flags, unsigned long newsp) return ret; } -#endif +static long do_fcntl(int fd, int cmd, unsigned long arg) +{ + struct flock fl; + struct target_flock *target_fl = (void *)arg; + long ret; + + switch(cmd) { + case TARGET_F_GETLK: + ret = fcntl(fd, cmd, &fl); + if (ret == 0) { + target_fl->l_type = tswap16(fl.l_type); + target_fl->l_whence = tswap16(fl.l_whence); + target_fl->l_start = tswapl(fl.l_start); + target_fl->l_len = tswapl(fl.l_len); + target_fl->l_pid = tswapl(fl.l_pid); + } + break; + + case TARGET_F_SETLK: + case TARGET_F_SETLKW: + fl.l_type = tswap16(target_fl->l_type); + fl.l_whence = tswap16(target_fl->l_whence); + fl.l_start = tswapl(target_fl->l_start); + fl.l_len = tswapl(target_fl->l_len); + fl.l_pid = tswapl(target_fl->l_pid); + ret = fcntl(fd, cmd, &fl); + break; + + case TARGET_F_GETLK64: + case TARGET_F_SETLK64: + case TARGET_F_SETLKW64: + ret = -1; + errno = EINVAL; + break; + + default: + ret = fcntl(fd, cmd, arg); + break; + } + return ret; +} + #define high2lowuid(x) (x) #define high2lowgid(x) (x) @@ -1188,11 +1207,43 @@ int do_fork(CPUX86State *env, unsigned int flags, unsigned long newsp) void syscall_init(void) { + IOCTLEntry *ie; + const argtype *arg_type; + int size; + #define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def); #define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def); #include "syscall_types.h" #undef STRUCT #undef STRUCT_SPECIAL + + /* we patch the ioctl size if necessary. We rely on the fact that + no ioctl has all the bits at '1' in the size field */ + ie = ioctl_entries; + while (ie->target_cmd != 0) { + if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) == + TARGET_IOC_SIZEMASK) { + arg_type = ie->arg_type; + if (arg_type[0] != TYPE_PTR) { + fprintf(stderr, "cannot patch size for ioctl 0x%x\n", + ie->target_cmd); + exit(1); + } + arg_type++; + size = thunk_type_size(arg_type, 0); + ie->target_cmd = (ie->target_cmd & + ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) | + (size << TARGET_IOC_SIZESHIFT); + } + /* automatic consistency check if same arch */ +#if defined(__i386__) && defined(TARGET_I386) + if (ie->target_cmd != ie->host_cmd) { + fprintf(stderr, "ERROR: ioctl: target=0x%x host=0x%x\n", + ie->target_cmd, ie->host_cmd); + } +#endif + ie++; + } } long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1215,6 +1266,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, ret = 0; /* avoid warning */ break; case TARGET_NR_read: + page_unprotect_range((void *)arg2, arg3); ret = get_errno(read(arg1, (void *)arg2, arg3)); break; case TARGET_NR_write: @@ -1386,11 +1438,13 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, struct tms tms; ret = get_errno(times(&tms)); if (tmsp) { - tmsp->tms_utime = tswapl(tms.tms_utime); - tmsp->tms_stime = tswapl(tms.tms_stime); - tmsp->tms_cutime = tswapl(tms.tms_cutime); - tmsp->tms_cstime = tswapl(tms.tms_cstime); + tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime)); + tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime)); + tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime)); + tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime)); } + if (!is_error(ret)) + ret = host_to_target_clock_t(ret); } break; case TARGET_NR_prof: @@ -1420,42 +1474,8 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, ret = do_ioctl(arg1, arg2, arg3); break; case TARGET_NR_fcntl: - { - struct flock fl; - struct target_flock *target_fl = (void *)arg3; - - switch(arg2) { - case TARGET_F_GETLK: - ret = get_errno(fcntl(arg1, arg2, &fl)); - if (ret == 0) { - target_fl->l_type = tswap16(fl.l_type); - target_fl->l_whence = tswap16(fl.l_whence); - target_fl->l_start = tswapl(fl.l_start); - target_fl->l_len = tswapl(fl.l_len); - target_fl->l_pid = tswapl(fl.l_pid); - } - break; - - case TARGET_F_SETLK: - case TARGET_F_SETLKW: - fl.l_type = tswap16(target_fl->l_type); - fl.l_whence = tswap16(target_fl->l_whence); - fl.l_start = tswapl(target_fl->l_start); - fl.l_len = tswapl(target_fl->l_len); - fl.l_pid = tswapl(target_fl->l_pid); - ret = get_errno(fcntl(arg1, arg2, &fl)); - break; - - case TARGET_F_GETLK64: - case TARGET_F_SETLK64: - case TARGET_F_SETLKW64: - goto unimplemented; - default: - ret = get_errno(fcntl(arg1, arg2, arg3)); - break; - } + ret = get_errno(do_fcntl(arg1, arg2, arg3)); break; - } case TARGET_NR_mpx: goto unimplemented; case TARGET_NR_setpgid: @@ -1704,7 +1724,15 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, } break; case TARGET_NR_getrusage: - goto unimplemented; + { + struct rusage rusage; + struct target_rusage *target_rusage = (void *)arg2; + ret = get_errno(getrusage(arg1, &rusage)); + if (!is_error(ret)) { + host_to_target_rusage(target_rusage, &rusage); + } + } + break; case TARGET_NR_gettimeofday: { struct target_timeval *target_tv = (void *)arg1; @@ -1752,7 +1780,17 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, } break; case TARGET_NR_select: - goto unimplemented; + { + struct target_sel_arg_struct *sel = (void *)arg1; + sel->n = tswapl(sel->n); + sel->inp = tswapl(sel->inp); + sel->outp = tswapl(sel->outp); + sel->exp = tswapl(sel->exp); + sel->tvp = tswapl(sel->tvp); + ret = do_select(sel->n, (void *)sel->inp, (void *)sel->outp, + (void *)sel->exp, (void *)sel->tvp); + } + break; case TARGET_NR_symlink: ret = get_errno(symlink((const char *)arg1, (const char *)arg2)); break; @@ -1770,8 +1808,8 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, goto unimplemented; case TARGET_NR_readdir: goto unimplemented; -#ifdef TARGET_I386 case TARGET_NR_mmap: +#if defined(TARGET_I386) || defined(TARGET_ARM) { uint32_t v1, v2, v3, v4, v5, v6, *vptr; vptr = (uint32_t *)arg1; @@ -1781,25 +1819,31 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, v4 = tswap32(vptr[3]); v5 = tswap32(vptr[4]); v6 = tswap32(vptr[5]); - ret = get_errno((long)mmap((void *)v1, v2, v3, v4, v5, v6)); + ret = get_errno(target_mmap(v1, v2, v3, + target_to_host_bitmask(v4, mmap_flags_tbl), + v5, v6)); } - break; -#endif -#ifdef TARGET_I386 - case TARGET_NR_mmap2: #else - case TARGET_NR_mmap: + ret = get_errno(target_mmap(arg1, arg2, arg3, + target_to_host_bitmask(arg4, mmap_flags_tbl), + arg5, + arg6)); #endif - ret = get_errno((long)mmap((void *)arg1, arg2, arg3, arg4, arg5, arg6)); + break; + case TARGET_NR_mmap2: + ret = get_errno(target_mmap(arg1, arg2, arg3, + target_to_host_bitmask(arg4, mmap_flags_tbl), + arg5, + arg6 << TARGET_PAGE_BITS)); break; case TARGET_NR_munmap: - ret = get_errno(munmap((void *)arg1, arg2)); + ret = get_errno(target_munmap(arg1, arg2)); break; case TARGET_NR_mprotect: - ret = get_errno(mprotect((void *)arg1, arg2, arg3)); + ret = get_errno(target_mprotect(arg1, arg2, arg3)); break; case TARGET_NR_mremap: - ret = get_errno((long)mremap((void *)arg1, arg2, arg3, arg4)); + ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5)); break; case TARGET_NR_msync: ret = get_errno(msync((void *)arg1, arg2, arg3)); @@ -1954,24 +1998,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, if (status_ptr) *status_ptr = tswap32(status); if (target_rusage) { - target_rusage->ru_utime.tv_sec = tswapl(rusage.ru_utime.tv_sec); - target_rusage->ru_utime.tv_usec = tswapl(rusage.ru_utime.tv_usec); - target_rusage->ru_stime.tv_sec = tswapl(rusage.ru_stime.tv_sec); - target_rusage->ru_stime.tv_usec = tswapl(rusage.ru_stime.tv_usec); - target_rusage->ru_maxrss = tswapl(rusage.ru_maxrss); - target_rusage->ru_ixrss = tswapl(rusage.ru_ixrss); - target_rusage->ru_idrss = tswapl(rusage.ru_idrss); - target_rusage->ru_isrss = tswapl(rusage.ru_isrss); - target_rusage->ru_minflt = tswapl(rusage.ru_minflt); - target_rusage->ru_majflt = tswapl(rusage.ru_majflt); - target_rusage->ru_nswap = tswapl(rusage.ru_nswap); - target_rusage->ru_inblock = tswapl(rusage.ru_inblock); - target_rusage->ru_oublock = tswapl(rusage.ru_oublock); - target_rusage->ru_msgsnd = tswapl(rusage.ru_msgsnd); - target_rusage->ru_msgrcv = tswapl(rusage.ru_msgrcv); - target_rusage->ru_nsignals = tswapl(rusage.ru_nsignals); - target_rusage->ru_nvcsw = tswapl(rusage.ru_nvcsw); - target_rusage->ru_nivcsw = tswapl(rusage.ru_nivcsw); + host_to_target_rusage(target_rusage, &rusage); } } } @@ -2052,7 +2079,47 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, case TARGET_NR_getdents: #if TARGET_LONG_SIZE != 4 #error not supported -#endif +#elif TARGET_LONG_SIZE == 4 && HOST_LONG_SIZE == 8 + { + struct target_dirent *target_dirp = (void *)arg2; + struct dirent *dirp; + long count = arg3; + + dirp = malloc(count); + if (!dirp) + return -ENOMEM; + + ret = get_errno(sys_getdents(arg1, dirp, count)); + if (!is_error(ret)) { + struct dirent *de; + struct target_dirent *tde; + int len = ret; + int reclen, treclen; + int count1, tnamelen; + + count1 = 0; + de = dirp; + tde = target_dirp; + while (len > 0) { + reclen = de->d_reclen; + treclen = reclen - (2 * (sizeof(long) - sizeof(target_long))); + tde->d_reclen = tswap16(treclen); + tde->d_ino = tswapl(de->d_ino); + tde->d_off = tswapl(de->d_off); + tnamelen = treclen - (2 * sizeof(target_long) + 2); + if (tnamelen > 256) + tnamelen = 256; + strncpy(tde->d_name, de->d_name, tnamelen); + de = (struct dirent *)((char *)de + reclen); + len -= reclen; + tde = (struct dirent *)((char *)tde + treclen); + count1 += treclen; + } + ret = count1; + } + free(dirp); + } +#else { struct dirent *dirp = (void *)arg2; long count = arg3; @@ -2075,6 +2142,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, } } } +#endif break; case TARGET_NR_getdents64: { @@ -2269,9 +2337,12 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, case TARGET_NR_prctl: goto unimplemented; case TARGET_NR_pread: - goto unimplemented; + page_unprotect_range((void *)arg2, arg3); + ret = get_errno(pread(arg1, (void *)arg2, arg3, arg4)); + break; case TARGET_NR_pwrite: - goto unimplemented; + ret = get_errno(pwrite(arg1, (void *)arg2, arg3, arg4)); + break; case TARGET_NR_chown: ret = get_errno(chown((const char *)arg1, arg2, arg3)); break; @@ -2447,7 +2518,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, ret = get_errno(fcntl(arg1, arg2, &fl)); break; default: - ret = get_errno(fcntl(arg1, arg2, arg3)); + ret = get_errno(do_fcntl(arg1, arg2, arg3)); break; } break;