Commit 6a24a778baa2ced9982d036db90bf7ae98b4669a
1 parent
a2155fcc
Implement fstatat64() syscall (by Kirill Shutemov).
Move the transformation of struct stat64 into a separate function and implement fstatat64() using it. Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5268 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
83 additions
and
58 deletions
linux-user/syscall.c
| @@ -156,6 +156,7 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \ | @@ -156,6 +156,7 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \ | ||
| 156 | #define __NR_sys_faccessat __NR_faccessat | 156 | #define __NR_sys_faccessat __NR_faccessat |
| 157 | #define __NR_sys_fchmodat __NR_fchmodat | 157 | #define __NR_sys_fchmodat __NR_fchmodat |
| 158 | #define __NR_sys_fchownat __NR_fchownat | 158 | #define __NR_sys_fchownat __NR_fchownat |
| 159 | +#define __NR_sys_fstatat64 __NR_fstatat64 | ||
| 159 | #define __NR_sys_getcwd1 __NR_getcwd | 160 | #define __NR_sys_getcwd1 __NR_getcwd |
| 160 | #define __NR_sys_getdents __NR_getdents | 161 | #define __NR_sys_getdents __NR_getdents |
| 161 | #define __NR_sys_getdents64 __NR_getdents64 | 162 | #define __NR_sys_getdents64 __NR_getdents64 |
| @@ -200,6 +201,10 @@ _syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname, | @@ -200,6 +201,10 @@ _syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname, | ||
| 200 | _syscall5(int,sys_fchownat,int,dirfd,const char *,pathname, | 201 | _syscall5(int,sys_fchownat,int,dirfd,const char *,pathname, |
| 201 | uid_t,owner,gid_t,group,int,flags) | 202 | uid_t,owner,gid_t,group,int,flags) |
| 202 | #endif | 203 | #endif |
| 204 | +#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64) | ||
| 205 | +_syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname, | ||
| 206 | + struct stat *,buf,int,flags) | ||
| 207 | +#endif | ||
| 203 | _syscall2(int,sys_getcwd1,char *,buf,size_t,size) | 208 | _syscall2(int,sys_getcwd1,char *,buf,size_t,size) |
| 204 | #if TARGET_ABI_BITS == 32 | 209 | #if TARGET_ABI_BITS == 32 |
| 205 | _syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count); | 210 | _syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count); |
| @@ -3149,6 +3154,67 @@ static inline abi_long host_to_target_timespec(abi_ulong target_addr, | @@ -3149,6 +3154,67 @@ static inline abi_long host_to_target_timespec(abi_ulong target_addr, | ||
| 3149 | return 0; | 3154 | return 0; |
| 3150 | } | 3155 | } |
| 3151 | 3156 | ||
| 3157 | +#ifdef TARGET_NR_stat64 | ||
| 3158 | +static inline abi_long host_to_target_stat64(void *cpu_env, | ||
| 3159 | + abi_ulong target_addr, | ||
| 3160 | + struct stat *host_st) | ||
| 3161 | +{ | ||
| 3162 | +#ifdef TARGET_ARM | ||
| 3163 | + if (((CPUARMState *)cpu_env)->eabi) { | ||
| 3164 | + struct target_eabi_stat64 *target_st; | ||
| 3165 | + | ||
| 3166 | + if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0)) | ||
| 3167 | + return -TARGET_EFAULT; | ||
| 3168 | + memset(target_st, 0, sizeof(struct target_eabi_stat64)); | ||
| 3169 | + __put_user(host_st->st_dev, &target_st->st_dev); | ||
| 3170 | + __put_user(host_st->st_ino, &target_st->st_ino); | ||
| 3171 | +#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO | ||
| 3172 | + __put_user(host_st->st_ino, &target_st->__st_ino); | ||
| 3173 | +#endif | ||
| 3174 | + __put_user(host_st->st_mode, &target_st->st_mode); | ||
| 3175 | + __put_user(host_st->st_nlink, &target_st->st_nlink); | ||
| 3176 | + __put_user(host_st->st_uid, &target_st->st_uid); | ||
| 3177 | + __put_user(host_st->st_gid, &target_st->st_gid); | ||
| 3178 | + __put_user(host_st->st_rdev, &target_st->st_rdev); | ||
| 3179 | + __put_user(host_st->st_size, &target_st->st_size); | ||
| 3180 | + __put_user(host_st->st_blksize, &target_st->st_blksize); | ||
| 3181 | + __put_user(host_st->st_blocks, &target_st->st_blocks); | ||
| 3182 | + __put_user(host_st->st_atime, &target_st->target_st_atime); | ||
| 3183 | + __put_user(host_st->st_mtime, &target_st->target_st_mtime); | ||
| 3184 | + __put_user(host_st->st_ctime, &target_st->target_st_ctime); | ||
| 3185 | + unlock_user_struct(target_st, target_addr, 1); | ||
| 3186 | + } else | ||
| 3187 | +#endif | ||
| 3188 | + { | ||
| 3189 | + struct target_stat64 *target_st; | ||
| 3190 | + | ||
| 3191 | + if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0)) | ||
| 3192 | + return -TARGET_EFAULT; | ||
| 3193 | + memset(target_st, 0, sizeof(struct target_stat64)); | ||
| 3194 | + __put_user(host_st->st_dev, &target_st->st_dev); | ||
| 3195 | + __put_user(host_st->st_ino, &target_st->st_ino); | ||
| 3196 | +#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO | ||
| 3197 | + __put_user(host_st->st_ino, &target_st->__st_ino); | ||
| 3198 | +#endif | ||
| 3199 | + __put_user(host_st->st_mode, &target_st->st_mode); | ||
| 3200 | + __put_user(host_st->st_nlink, &target_st->st_nlink); | ||
| 3201 | + __put_user(host_st->st_uid, &target_st->st_uid); | ||
| 3202 | + __put_user(host_st->st_gid, &target_st->st_gid); | ||
| 3203 | + __put_user(host_st->st_rdev, &target_st->st_rdev); | ||
| 3204 | + /* XXX: better use of kernel struct */ | ||
| 3205 | + __put_user(host_st->st_size, &target_st->st_size); | ||
| 3206 | + __put_user(host_st->st_blksize, &target_st->st_blksize); | ||
| 3207 | + __put_user(host_st->st_blocks, &target_st->st_blocks); | ||
| 3208 | + __put_user(host_st->st_atime, &target_st->target_st_atime); | ||
| 3209 | + __put_user(host_st->st_mtime, &target_st->target_st_mtime); | ||
| 3210 | + __put_user(host_st->st_ctime, &target_st->target_st_ctime); | ||
| 3211 | + unlock_user_struct(target_st, target_addr, 1); | ||
| 3212 | + } | ||
| 3213 | + | ||
| 3214 | + return 0; | ||
| 3215 | +} | ||
| 3216 | +#endif | ||
| 3217 | + | ||
| 3152 | #if defined(USE_NPTL) | 3218 | #if defined(USE_NPTL) |
| 3153 | /* ??? Using host futex calls even when target atomic operations | 3219 | /* ??? Using host futex calls even when target atomic operations |
| 3154 | are not really atomic probably breaks things. However implementing | 3220 | are not really atomic probably breaks things. However implementing |
| @@ -5142,7 +5208,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, | @@ -5142,7 +5208,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, | ||
| 5142 | goto efault; | 5208 | goto efault; |
| 5143 | ret = get_errno(stat(path(p), &st)); | 5209 | ret = get_errno(stat(path(p), &st)); |
| 5144 | unlock_user(p, arg1, 0); | 5210 | unlock_user(p, arg1, 0); |
| 5145 | - goto do_stat64; | 5211 | + if (!is_error(ret)) |
| 5212 | + ret = host_to_target_stat64(cpu_env, arg2, &st); | ||
| 5213 | + break; | ||
| 5146 | #endif | 5214 | #endif |
| 5147 | #ifdef TARGET_NR_lstat64 | 5215 | #ifdef TARGET_NR_lstat64 |
| 5148 | case TARGET_NR_lstat64: | 5216 | case TARGET_NR_lstat64: |
| @@ -5150,67 +5218,24 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, | @@ -5150,67 +5218,24 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, | ||
| 5150 | goto efault; | 5218 | goto efault; |
| 5151 | ret = get_errno(lstat(path(p), &st)); | 5219 | ret = get_errno(lstat(path(p), &st)); |
| 5152 | unlock_user(p, arg1, 0); | 5220 | unlock_user(p, arg1, 0); |
| 5153 | - goto do_stat64; | 5221 | + if (!is_error(ret)) |
| 5222 | + ret = host_to_target_stat64(cpu_env, arg2, &st); | ||
| 5223 | + break; | ||
| 5154 | #endif | 5224 | #endif |
| 5155 | #ifdef TARGET_NR_fstat64 | 5225 | #ifdef TARGET_NR_fstat64 |
| 5156 | case TARGET_NR_fstat64: | 5226 | case TARGET_NR_fstat64: |
| 5157 | - { | ||
| 5158 | - ret = get_errno(fstat(arg1, &st)); | ||
| 5159 | - do_stat64: | ||
| 5160 | - if (!is_error(ret)) { | ||
| 5161 | -#ifdef TARGET_ARM | ||
| 5162 | - if (((CPUARMState *)cpu_env)->eabi) { | ||
| 5163 | - struct target_eabi_stat64 *target_st; | ||
| 5164 | - | ||
| 5165 | - if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0)) | ||
| 5166 | - goto efault; | ||
| 5167 | - memset(target_st, 0, sizeof(struct target_eabi_stat64)); | ||
| 5168 | - __put_user(st.st_dev, &target_st->st_dev); | ||
| 5169 | - __put_user(st.st_ino, &target_st->st_ino); | ||
| 5170 | -#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO | ||
| 5171 | - __put_user(st.st_ino, &target_st->__st_ino); | ||
| 5172 | -#endif | ||
| 5173 | - __put_user(st.st_mode, &target_st->st_mode); | ||
| 5174 | - __put_user(st.st_nlink, &target_st->st_nlink); | ||
| 5175 | - __put_user(st.st_uid, &target_st->st_uid); | ||
| 5176 | - __put_user(st.st_gid, &target_st->st_gid); | ||
| 5177 | - __put_user(st.st_rdev, &target_st->st_rdev); | ||
| 5178 | - __put_user(st.st_size, &target_st->st_size); | ||
| 5179 | - __put_user(st.st_blksize, &target_st->st_blksize); | ||
| 5180 | - __put_user(st.st_blocks, &target_st->st_blocks); | ||
| 5181 | - __put_user(st.st_atime, &target_st->target_st_atime); | ||
| 5182 | - __put_user(st.st_mtime, &target_st->target_st_mtime); | ||
| 5183 | - __put_user(st.st_ctime, &target_st->target_st_ctime); | ||
| 5184 | - unlock_user_struct(target_st, arg2, 1); | ||
| 5185 | - } else | 5227 | + ret = get_errno(fstat(arg1, &st)); |
| 5228 | + if (!is_error(ret)) | ||
| 5229 | + ret = host_to_target_stat64(cpu_env, arg2, &st); | ||
| 5230 | + break; | ||
| 5186 | #endif | 5231 | #endif |
| 5187 | - { | ||
| 5188 | - struct target_stat64 *target_st; | ||
| 5189 | - | ||
| 5190 | - if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0)) | ||
| 5191 | - goto efault; | ||
| 5192 | - memset(target_st, 0, sizeof(struct target_stat64)); | ||
| 5193 | - __put_user(st.st_dev, &target_st->st_dev); | ||
| 5194 | - __put_user(st.st_ino, &target_st->st_ino); | ||
| 5195 | -#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO | ||
| 5196 | - __put_user(st.st_ino, &target_st->__st_ino); | ||
| 5197 | -#endif | ||
| 5198 | - __put_user(st.st_mode, &target_st->st_mode); | ||
| 5199 | - __put_user(st.st_nlink, &target_st->st_nlink); | ||
| 5200 | - __put_user(st.st_uid, &target_st->st_uid); | ||
| 5201 | - __put_user(st.st_gid, &target_st->st_gid); | ||
| 5202 | - __put_user(st.st_rdev, &target_st->st_rdev); | ||
| 5203 | - /* XXX: better use of kernel struct */ | ||
| 5204 | - __put_user(st.st_size, &target_st->st_size); | ||
| 5205 | - __put_user(st.st_blksize, &target_st->st_blksize); | ||
| 5206 | - __put_user(st.st_blocks, &target_st->st_blocks); | ||
| 5207 | - __put_user(st.st_atime, &target_st->target_st_atime); | ||
| 5208 | - __put_user(st.st_mtime, &target_st->target_st_mtime); | ||
| 5209 | - __put_user(st.st_ctime, &target_st->target_st_ctime); | ||
| 5210 | - unlock_user_struct(target_st, arg2, 1); | ||
| 5211 | - } | ||
| 5212 | - } | ||
| 5213 | - } | 5232 | +#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64) |
| 5233 | + case TARGET_NR_fstatat64: | ||
| 5234 | + if (!(p = lock_user_string(arg2))) | ||
| 5235 | + goto efault; | ||
| 5236 | + ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4)); | ||
| 5237 | + if (!is_error(ret)) | ||
| 5238 | + ret = host_to_target_stat64(cpu_env, arg3, &st); | ||
| 5214 | break; | 5239 | break; |
| 5215 | #endif | 5240 | #endif |
| 5216 | #ifdef USE_UID16 | 5241 | #ifdef USE_UID16 |