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

Yury Norov ynorov at caviumnetworks.com
Mon Nov 2 15:30:43 PST 2015


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 at caviumnetworks.com>
Reviewed-by: David Daney <david.daney at cavium.com>
---
 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




More information about the linux-arm-kernel mailing list