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 <yno...@caviumnetworks.com>
Reviewed-by: David Daney <david.da...@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

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

Reply via email to