Commit 6a24a778baa2ced9982d036db90bf7ae98b4669a

Authored by balrog
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