This patch puts stat64 functionality into a function rather than using
gotos for all the locations that copy stat64 buffers to user space.
This patch is necessary for following fstatat64 syscall patch.
Index: qemu/linux-user/syscall.c
===================================================================
--- qemu.orig/linux-user/syscall.c	2007-09-19 06:28:30.000000000 -0600
+++ qemu/linux-user/syscall.c	2007-09-19 06:28:34.000000000 -0600
@@ -526,6 +526,77 @@
     return 0;
 }
 
+#ifdef TARGET_ARM
+#define copy_to_user_statbuf64_wrapper(tsb,hsb)		\
+	((((CPUARMState *)cpu_env)->eabi)		\
+	 ? copy_to_user_statbuf64_eabi((tsb),(hsb))	\
+	 : copy_to_user_statbuf64((tsb),(hsb)))
+#else
+#define copy_to_user_statbuf64_wrapper(tsb,hsb)		\
+	copy_to_user_eabi_statbuf64((tsb),(hsb))
+#endif
+
+#ifdef TARGET_ARM
+static inline long copy_to_user_statbuf64_eabi(void *gen_target_stbuf,
+					       const struct stat *host_stbuf)
+{
+    struct target_eabi_stat64 *target_stbuf = (struct target_eabi_stat64 *)gen_target_stbuf;
+    int i;
+
+    if( !access_ok(VERIFY_WRITE,target_stbuf,sizeof(struct target_eabi_stat64)) ) return -EFAULT;
+    memset(target_stbuf, 0, sizeof(struct target_eabi_stat64));
+    /* use __put_user() since we just checked that the buffer is valid  */
+    __put_user(host_stbuf->st_dev, &target_stbuf->st_dev);
+    __put_user(host_stbuf->st_ino, &target_stbuf->st_ino);
+#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
+    __put_user(host_stbuf->st_ino, &target_stbuf->__st_ino);
+#endif
+    __put_user(host_stbuf->st_mode, &target_stbuf->st_mode);
+    __put_user(host_stbuf->st_nlink, &target_stbuf->st_nlink);
+    __put_user(host_stbuf->st_uid, &target_stbuf->st_uid);
+    __put_user(host_stbuf->st_gid, &target_stbuf->st_gid);
+    __put_user(host_stbuf->st_rdev, &target_stbuf->st_rdev);
+    /* XXX: better use of kernel struct */
+    __put_user(host_stbuf->st_size, &target_stbuf->st_size);
+    __put_user(host_stbuf->st_blksize, &target_stbuf->st_blksize);
+    __put_user(host_stbuf->st_blocks, &target_stbuf->st_blocks);
+    __put_user(host_stbuf->st_atime, &target_stbuf->target_st_atime);
+    __put_user(host_stbuf->st_mtime, &target_stbuf->target_st_mtime);
+    __put_user(host_stbuf->st_ctime, &target_stbuf->target_st_ctime);
+
+    return 0;
+}
+#endif
+
+static inline long copy_to_user_statbuf64(void *gen_target_stbuf,
+					  const struct stat *host_stbuf)
+{
+    struct target_stat64 *target_stbuf = (struct target_stat64 *)gen_target_stbuf;
+    gemu_log("%s()\n", __func__);
+    if( !access_ok(VERIFY_WRITE,target_stbuf,sizeof(struct target_stat64)) ) return -EFAULT;
+    memset(target_stbuf, 0, sizeof(struct target_stat64));
+    /* use __put_user() since we just checked that the buffer is valid  */
+    __put_user(host_stbuf->st_dev, &target_stbuf->st_dev);
+    __put_user(host_stbuf->st_ino, &target_stbuf->st_ino);
+#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
+    __put_user(host_stbuf->st_ino, &target_stbuf->__st_ino);
+#endif
+    __put_user(host_stbuf->st_mode, &target_stbuf->st_mode);
+    __put_user(host_stbuf->st_nlink, &target_stbuf->st_nlink);
+    __put_user(host_stbuf->st_uid, &target_stbuf->st_uid);
+    __put_user(host_stbuf->st_gid, &target_stbuf->st_gid);
+    __put_user(host_stbuf->st_rdev, &target_stbuf->st_rdev);
+    /* XXX: better use of kernel struct */
+    __put_user(host_stbuf->st_size, &target_stbuf->st_size);
+    __put_user(host_stbuf->st_blksize, &target_stbuf->st_blksize);
+    __put_user(host_stbuf->st_blocks, &target_stbuf->st_blocks);
+    __put_user(host_stbuf->st_atime, &target_stbuf->target_st_atime);
+    __put_user(host_stbuf->st_mtime, &target_stbuf->target_st_mtime);
+    __put_user(host_stbuf->st_ctime, &target_stbuf->target_st_ctime);
+    return 0;
+}
+
+
 static inline long copy_from_user_timeval(struct timeval *tv,
                                           struct target_timeval *target_tv)
 {
@@ -4562,7 +4633,10 @@
         if( !access_ok(VERIFY_READ,p,1) ) return -EFAULT;
         ret = get_errno(stat(path(p), &st));
         unlock_user(p, arg1, 0);
-        goto do_stat64;
+        if (!is_error(ret)
+            && copy_to_user_statbuf64_wrapper(arg2,&st))
+            return -EFAULT;
+	break;
 #endif
 #ifdef TARGET_NR_lstat64
     case TARGET_NR_lstat64:
@@ -4570,65 +4644,18 @@
         if( !access_ok(VERIFY_READ,p,1) ) return -EFAULT;
         ret = get_errno(lstat(path(p), &st));
         unlock_user(p, arg1, 0);
-        goto do_stat64;
+        if (!is_error(ret)
+            && copy_to_user_statbuf64_wrapper(arg2,&st))
+            return -EFAULT;
+	break;
 #endif
 #ifdef TARGET_NR_fstat64
     case TARGET_NR_fstat64:
-        {
-            ret = get_errno(fstat(arg1, &st));
-        do_stat64:
-            if (!is_error(ret)) {
-#ifdef TARGET_ARM
-                if (((CPUARMState *)cpu_env)->eabi) {
-                    struct target_eabi_stat64 *target_st = (struct target_eabi_stat64 *)arg2;
-		    if( !access_ok(VERIFY_WRITE,target_st,sizeof(struct target_eabi_stat64)) ) return -EFAULT;
-                    memset(target_st, 0, sizeof(struct target_eabi_stat64));
-                    /* use __put_user() since we just checked that the buffer is valid  */
-                    __put_user(st.st_dev, &target_st->st_dev);
-                    __put_user(st.st_ino, &target_st->st_ino);
-#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
-                    __put_user(st.st_ino, &target_st->__st_ino);
-#endif
-                    __put_user(st.st_mode, &target_st->st_mode);
-                    __put_user(st.st_nlink, &target_st->st_nlink);
-                    __put_user(st.st_uid, &target_st->st_uid);
-                    __put_user(st.st_gid, &target_st->st_gid);
-                    __put_user(st.st_rdev, &target_st->st_rdev);
-                    /* XXX: better use of kernel struct */
-                    __put_user(st.st_size, &target_st->st_size);
-                    __put_user(st.st_blksize, &target_st->st_blksize);
-                    __put_user(st.st_blocks, &target_st->st_blocks);
-                    __put_user(st.st_atime, &target_st->target_st_atime);
-                    __put_user(st.st_mtime, &target_st->target_st_mtime);
-                    __put_user(st.st_ctime, &target_st->target_st_ctime);
-                } else
-#endif
-                {
-                    struct target_stat64 *target_st = (struct target_stat64 *)arg2;
-		    if( !access_ok(VERIFY_WRITE,target_st,sizeof(struct target_stat64)) ) return -EFAULT;
-                    memset(target_st, 0, sizeof(struct target_stat64));
-                    /* use __put_user() since we just checked that the buffer is valid  */
-                    __put_user(st.st_dev, &target_st->st_dev);
-                    __put_user(st.st_ino, &target_st->st_ino);
-#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
-                    __put_user(st.st_ino, &target_st->__st_ino);
-#endif
-                    __put_user(st.st_mode, &target_st->st_mode);
-                    __put_user(st.st_nlink, &target_st->st_nlink);
-                    __put_user(st.st_uid, &target_st->st_uid);
-                    __put_user(st.st_gid, &target_st->st_gid);
-                    __put_user(st.st_rdev, &target_st->st_rdev);
-                    /* XXX: better use of kernel struct */
-                    __put_user(st.st_size, &target_st->st_size);
-                    __put_user(st.st_blksize, &target_st->st_blksize);
-                    __put_user(st.st_blocks, &target_st->st_blocks);
-                    __put_user(st.st_atime, &target_st->target_st_atime);
-                    __put_user(st.st_mtime, &target_st->target_st_mtime);
-                    __put_user(st.st_ctime, &target_st->target_st_ctime);
-                }
-            }
-        }
-        break;
+        ret = get_errno(fstat(arg1, &st));
+        if (!is_error(ret)
+            && copy_to_user_statbuf64_wrapper(arg2,&st))
+            return -EFAULT;
+	break;
 #endif
 #ifdef USE_UID16
     case TARGET_NR_lchown:

Reply via email to