[v2,1/2] sysdeps/stat: Handle 64-bit ino_t types on 32-bit hosts
Commit Message
On a 32-bit platform with a 64-bit ino_t type (__INO_T_MATCHES_INO64_T
defined) we want to update the stat struct to remove the padding as it
isn't required. As we don't have the padding we also need to update the
overflow checker to not access the undefined members.
2019-09-16 Alistair Francis <alistair.francis@wdc.com>
* sysdeps/unix/sysv/linux/generic/bits/stat.h: Handle 64-bit ino_t types
on 32-bit hosts.
* sysdeps/unix/sysv/linux/generic/wordsize-32/overflow.h: Likewise.
---
v2:
- Fix the #if logic
sysdeps/unix/sysv/linux/generic/bits/stat.h | 5 ++++-
sysdeps/unix/sysv/linux/generic/wordsize-32/overflow.h | 4 ++++
2 files changed, 8 insertions(+), 1 deletion(-)
Comments
On Wed, 18 Sep 2019, Alistair Francis wrote:
> On a 32-bit platform with a 64-bit ino_t type (__INO_T_MATCHES_INO64_T
> defined) we want to update the stat struct to remove the padding as it
> isn't required. As we don't have the padding we also need to update the
> overflow checker to not access the undefined members.
When posting a patch, please *always* say how it was tested. Typically
that would include running the glibc testsuite for at least one
configuration (but there may be exceptions, e.g. documentation patches).
> -#if defined __USE_FILE_OFFSET64
> +#if defined(__USE_FILE_OFFSET64) || __INO_T_MATCHES_INO64_T == 1
> +# if __INO_T_MATCHES_INO64_T == 1 && __OFF_T_MATCHES_OFF64_T != 1
The rule in glibc is that we compile with -Wundef and do not rely on
undefined macros being interpreted as 0 in #if.
Both __INO_T_MATCHES_INO64_T and __OFF_T_MATCHES_OFF64_T are in fact
defined/undefined macros, not macros that might sometimes be defined to 1
and sometimes to 0. So testing with == there is problematic; I'd expect
it to cause -Wundef errors for any existing 32-bit linux/generic
architecture where those macros are undefined (i.e. csky and nios2).
There are two possible approaches to fixing this.
(a) Do a preliminary patch that changes these macros from defined /
undefined to always-defined with 1 / 0 values. This involves updating a
lot of places that use the macros (mainly using __OFF_T_MATCHES_OFF64_T),
as well as ensuring that all bits/typesizes.h headers provide appropriate
definitions.
(b) Change this patch to do defined / undefined tests rather than testing
the macro values.
Also, when a macro is 0 / 1 I'd expect boolean tests just to test the
macro as a boolean (so plain "__INO_T_MATCHES_INO64_T" inside #if, not
"__INO_T_MATCHES_INO64_T == 1").
Also, if using "defined" with (), like a function call there should be a
space before '('.
@@ -40,7 +40,10 @@
/* Versions of the `xmknod' interface. */
#define _MKNOD_VER_LINUX 0
-#if defined __USE_FILE_OFFSET64
+#if defined(__USE_FILE_OFFSET64) || __INO_T_MATCHES_INO64_T == 1
+# if __INO_T_MATCHES_INO64_T == 1 && __OFF_T_MATCHES_OFF64_T != 1
+# error "ino_t and off_t must both be the same type"
+# endif
# define __field64(type, type64, name) type64 name
#elif __WORDSIZE == 64
# define __field64(type, type64, name) type name
@@ -36,12 +36,16 @@ static inline off_t lseek_overflow (loff_t res)
static inline int stat_overflow (struct stat *buf)
{
+#if __INO_T_MATCHES_INO64_T
+ return 0;
+#else
if (buf->__st_ino_pad == 0 && buf->__st_size_pad == 0
&& buf->__st_blocks_pad == 0)
return 0;
__set_errno (EOVERFLOW);
return -1;
+#endif
}
/* Note that f_files and f_ffree may validly be a sign-extended -1. */