[PATCH v6 14/17] aarch64: ilp32: use generic stat64 structure

From: Yury Norov
Date: Mon Nov 02 2015 - 18:34:21 EST


Generic 32-bit and AARCH32 stat64 structures has same names.
ILP32 needs generic stat64. So we can either make ILP32 mutual
exclusive with AARCH32, or introduce __stat64, and where needed,
cast stat64 to it with #define.

Second option requires to duplicate cp_new_stat64 code. But we
choose it, because it's more flexible to have independend support
for ABIs.

Signed-off-by: Yury Norov <ynorov@xxxxxxxxxxxxxxxxxx>
Reviewed-by: David Daney <david.daney@xxxxxxxxxx>
---
arch/arm64/kernel/sys_ilp32.c | 57 +++++++++++++++++++++++++++++++++++++++++
include/uapi/asm-generic/stat.h | 8 +++---
2 files changed, 62 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kernel/sys_ilp32.c b/arch/arm64/kernel/sys_ilp32.c
index 6c7d274..889f1d3 100644
--- a/arch/arm64/kernel/sys_ilp32.c
+++ b/arch/arm64/kernel/sys_ilp32.c
@@ -205,6 +205,63 @@ long ilp32_sys_sigaltstack(const stack_t __user *uss_ptr,
for stack_t might not be non-zero. */
#define sys_sigaltstack ilp32_sys_sigaltstack

+/* fs */
+
+#define sys_fcntl compat_sys_fcntl
+
+static long __cp_new_stat64(struct kstat *stat, struct __stat64 __user *statbuf)
+{
+ struct __stat64 tmp;
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.st_dev = huge_encode_dev(stat->dev);
+ tmp.st_rdev = huge_encode_dev(stat->rdev);
+
+ tmp.st_ino = stat->ino;
+ if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
+ return -EOVERFLOW;
+ tmp.st_mode = stat->mode;
+ tmp.st_nlink = stat->nlink;
+ tmp.st_uid = from_kuid_munged(current_user_ns(), stat->uid);
+ tmp.st_gid = from_kgid_munged(current_user_ns(), stat->gid);
+ tmp.st_atime = stat->atime.tv_sec;
+ tmp.st_atime_nsec = stat->atime.tv_nsec;
+ tmp.st_mtime = stat->mtime.tv_sec;
+ tmp.st_mtime_nsec = stat->mtime.tv_nsec;
+ tmp.st_ctime = stat->ctime.tv_sec;
+ tmp.st_ctime_nsec = stat->ctime.tv_nsec;
+ tmp.st_size = stat->size;
+ tmp.st_blocks = stat->blocks;
+ tmp.st_blksize = stat->blksize;
+ return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
+}
+
+long ilp32_sys_fstat64(int fd, struct __stat64 __user * statbuf)
+{
+ struct kstat stat;
+ int error = vfs_fstat(fd, &stat);
+
+ if (!error)
+ error = __cp_new_stat64(&stat, statbuf);
+
+ return error;
+}
+
+#define sys_newfstat ilp32_sys_fstat64
+
+long ilp32_sys_fstatat64(int dfd, const char __user * filename,
+ struct __stat64 __user * statbuf, int flag)
+{
+ struct kstat stat;
+ int error;
+
+ error = vfs_fstatat(dfd, filename, &stat, flag);
+ if (error)
+ return error;
+ return __cp_new_stat64(&stat, statbuf);
+}
+
+#define sys_newfstatat ilp32_sys_fstatat64

#include <asm/syscall.h>

diff --git a/include/uapi/asm-generic/stat.h b/include/uapi/asm-generic/stat.h
index bd8cad2..ae81e73 100644
--- a/include/uapi/asm-generic/stat.h
+++ b/include/uapi/asm-generic/stat.h
@@ -43,9 +43,7 @@ struct stat {
unsigned int __unused5;
};

-/* This matches struct stat64 in glibc2.1. Only used for 32 bit. */
-#if __BITS_PER_LONG != 64 || defined(__ARCH_WANT_STAT64)
-struct stat64 {
+struct __stat64 {
unsigned long long st_dev; /* Device. */
unsigned long long st_ino; /* File serial number. */
unsigned int st_mode; /* File mode. */
@@ -67,6 +65,10 @@ struct stat64 {
unsigned int __unused4;
unsigned int __unused5;
};
+
+#if __BITS_PER_LONG != 64 || defined(__ARCH_WANT_STAT64)
+/* This matches struct stat64 in glibc2.1. Only used for 32 bit. */
+#define stat64 __stat64
#endif

#endif /* __ASM_GENERIC_STAT_H */
--
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/