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 | 156 | #define __NR_sys_faccessat __NR_faccessat |
157 | 157 | #define __NR_sys_fchmodat __NR_fchmodat |
158 | 158 | #define __NR_sys_fchownat __NR_fchownat |
159 | +#define __NR_sys_fstatat64 __NR_fstatat64 | |
159 | 160 | #define __NR_sys_getcwd1 __NR_getcwd |
160 | 161 | #define __NR_sys_getdents __NR_getdents |
161 | 162 | #define __NR_sys_getdents64 __NR_getdents64 |
... | ... | @@ -200,6 +201,10 @@ _syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname, |
200 | 201 | _syscall5(int,sys_fchownat,int,dirfd,const char *,pathname, |
201 | 202 | uid_t,owner,gid_t,group,int,flags) |
202 | 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 | 208 | _syscall2(int,sys_getcwd1,char *,buf,size_t,size) |
204 | 209 | #if TARGET_ABI_BITS == 32 |
205 | 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 | 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 | 3218 | #if defined(USE_NPTL) |
3153 | 3219 | /* ??? Using host futex calls even when target atomic operations |
3154 | 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 | 5208 | goto efault; |
5143 | 5209 | ret = get_errno(stat(path(p), &st)); |
5144 | 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 | 5214 | #endif |
5147 | 5215 | #ifdef TARGET_NR_lstat64 |
5148 | 5216 | case TARGET_NR_lstat64: |
... | ... | @@ -5150,67 +5218,24 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
5150 | 5218 | goto efault; |
5151 | 5219 | ret = get_errno(lstat(path(p), &st)); |
5152 | 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 | 5224 | #endif |
5155 | 5225 | #ifdef TARGET_NR_fstat64 |
5156 | 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 | 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 | 5239 | break; |
5215 | 5240 | #endif |
5216 | 5241 | #ifdef USE_UID16 | ... | ... |