yann@1819: From d43f068e84513ed88392df4ca27d49ad01145fd2 Mon Sep 17 00:00:00 2001 yann@1819: From: Mike Frysinger yann@1819: Date: Sun, 6 Sep 2009 12:12:12 -0400 yann@1819: Subject: [PATCH 07/15] fstatat: fix up behavior on 32/64 bit hosts yann@1819: MIME-Version: 1.0 yann@1819: Content-Type: text/plain; charset=UTF-8 yann@1819: Content-Transfer-Encoding: 8bit yann@1819: yann@1819: The fstatat() syscall is a little funky in that it sometimes changes name yann@1819: between 32 and 64 bit hosts, but it should always operate on a 64bit stat yann@1819: structure. So for the fstatat() function, make sure we convert it from a yann@1819: 64bit kstat to a 32bit stat. yann@1819: yann@1819: Along these lines, we need to restore the __xstat32_conv() function. yann@1819: yann@1819: Reported-by: Timo Teräs yann@1819: Signed-off-by: Mike Frysinger yann@1819: Signed-off-by: Bernhard Reutner-Fischer yann@1819: --- yann@1819: libc/sysdeps/linux/common/fstatat.c | 9 +++++++-- yann@1819: libc/sysdeps/linux/common/fstatat64.c | 5 +++++ yann@1819: libc/sysdeps/linux/common/xstatconv.c | 19 +++++++++++++++++++ yann@1819: libc/sysdeps/linux/common/xstatconv.h | 1 + yann@1819: 4 files changed, 32 insertions(+), 2 deletions(-) yann@1819: yann@1819: diff --git a/libc/sysdeps/linux/common/fstatat.c b/libc/sysdeps/linux/common/fstatat.c yann@1819: index 149c189..33daa7c 100644 yann@1819: --- a/libc/sysdeps/linux/common/fstatat.c yann@1819: +++ b/libc/sysdeps/linux/common/fstatat.c yann@1819: @@ -10,15 +10,20 @@ yann@1819: #include yann@1819: #include "xstatconv.h" yann@1819: yann@1819: +/* 64bit ports tend to favor newfstatat() */ yann@1819: +#ifdef __NR_newfstatat yann@1819: +# define __NR_fstatat64 __NR_newfstatat yann@1819: +#endif yann@1819: + yann@1819: #ifdef __NR_fstatat64 yann@1819: int fstatat(int fd, const char *file, struct stat *buf, int flag) yann@1819: { yann@1819: int ret; yann@1819: - struct kernel_stat kbuf; yann@1819: + struct kernel_stat64 kbuf; yann@1819: yann@1819: ret = INLINE_SYSCALL(fstatat64, 4, fd, file, &kbuf, flag); yann@1819: if (ret == 0) yann@1819: - __xstat_conv(&kbuf, buf); yann@1819: + __xstat32_conv(&kbuf, buf); yann@1819: yann@1819: return ret; yann@1819: } yann@1819: diff --git a/libc/sysdeps/linux/common/fstatat64.c b/libc/sysdeps/linux/common/fstatat64.c yann@1819: index 5ae1fad..95627af 100644 yann@1819: --- a/libc/sysdeps/linux/common/fstatat64.c yann@1819: +++ b/libc/sysdeps/linux/common/fstatat64.c yann@1819: @@ -12,6 +12,11 @@ yann@1819: yann@1819: #ifdef __UCLIBC_HAS_LFS__ yann@1819: yann@1819: +/* 64bit ports tend to favor newfstatat() */ yann@1819: +#ifdef __NR_newfstatat yann@1819: +# define __NR_fstatat64 __NR_newfstatat yann@1819: +#endif yann@1819: + yann@1819: #ifdef __NR_fstatat64 yann@1819: int fstatat64(int fd, const char *file, struct stat64 *buf, int flag) yann@1819: { yann@1819: diff --git a/libc/sysdeps/linux/common/xstatconv.c b/libc/sysdeps/linux/common/xstatconv.c yann@1819: index e575b26..50455c6 100644 yann@1819: --- a/libc/sysdeps/linux/common/xstatconv.c yann@1819: +++ b/libc/sysdeps/linux/common/xstatconv.c yann@1819: @@ -46,6 +46,25 @@ void attribute_hidden __xstat_conv(struct kernel_stat *kbuf, struct stat *buf) yann@1819: buf->st_ctim = kbuf->st_ctim; yann@1819: } yann@1819: yann@1819: +void __xstat32_conv(struct kernel_stat64 *kbuf, struct stat *buf) yann@1819: +{ yann@1819: + /* Convert to current kernel version of `struct stat64'. */ yann@1819: + memset(buf, 0x00, sizeof(*buf)); yann@1819: + buf->st_dev = kbuf->st_dev; yann@1819: + buf->st_ino = kbuf->st_ino; yann@1819: + buf->st_mode = kbuf->st_mode; yann@1819: + buf->st_nlink = kbuf->st_nlink; yann@1819: + buf->st_uid = kbuf->st_uid; yann@1819: + buf->st_gid = kbuf->st_gid; yann@1819: + buf->st_rdev = kbuf->st_rdev; yann@1819: + buf->st_size = kbuf->st_size; yann@1819: + buf->st_blksize = kbuf->st_blksize; yann@1819: + buf->st_blocks = kbuf->st_blocks; yann@1819: + buf->st_atim = kbuf->st_atim; yann@1819: + buf->st_mtim = kbuf->st_mtim; yann@1819: + buf->st_ctim = kbuf->st_ctim; yann@1819: +} yann@1819: + yann@1819: #ifdef __UCLIBC_HAS_LFS__ yann@1819: yann@1819: void attribute_hidden __xstat64_conv(struct kernel_stat64 *kbuf, struct stat64 *buf) yann@1819: diff --git a/libc/sysdeps/linux/common/xstatconv.h b/libc/sysdeps/linux/common/xstatconv.h yann@1819: index 57c8bcb..7568da8 100644 yann@1819: --- a/libc/sysdeps/linux/common/xstatconv.h yann@1819: +++ b/libc/sysdeps/linux/common/xstatconv.h yann@1819: @@ -26,6 +26,7 @@ yann@1819: #include yann@1819: yann@1819: extern void __xstat_conv(struct kernel_stat *kbuf, struct stat *buf) attribute_hidden; yann@1819: +extern void __xstat32_conv(struct kernel_stat64 *kbuf, struct stat *buf) attribute_hidden; yann@1819: #if defined __UCLIBC_HAS_LFS__ yann@1819: extern void __xstat64_conv(struct kernel_stat64 *kbuf, struct stat64 *buf) attribute_hidden; yann@1819: #endif yann@1819: -- yann@1819: 1.6.6.1 yann@1819: