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 |