[v4,1/2] sysdeps/stat: Handle 64-bit ino_t types on 32-bit hosts

Message ID 20191016234407.4306-1-alistair.francis@wdc.com
State New
Headers show
Series
  • [v4,1/2] sysdeps/stat: Handle 64-bit ino_t types on 32-bit hosts
Related show

Commit Message

Alistair Francis Oct. 16, 2019, 11:44 p.m.
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.

	* 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.
	* sysdeps/unix/sysv/linux/generic/xstat.c: Ensure __blkcnt_t == __blkcnt64_t
	if __INO_T_MATCHES_INO64_T is defined.
---
 sysdeps/unix/sysv/linux/generic/bits/stat.h            | 5 ++++-
 sysdeps/unix/sysv/linux/generic/wordsize-32/overflow.h | 4 ++++
 sysdeps/unix/sysv/linux/generic/xstat.c                | 5 +++++
 3 files changed, 13 insertions(+), 1 deletion(-)

-- 
2.23.0

Comments

Joseph Myers Oct. 18, 2019, 3:08 p.m. | #1
On Wed, 16 Oct 2019, Alistair Francis wrote:

> diff --git a/sysdeps/unix/sysv/linux/generic/xstat.c b/sysdeps/unix/sysv/linux/generic/xstat.c

> index 75ceb9bc74b..ece14fc5838 100644

> --- a/sysdeps/unix/sysv/linux/generic/xstat.c

> +++ b/sysdeps/unix/sysv/linux/generic/xstat.c

> @@ -28,6 +28,11 @@

>  #include <sysdep.h>

>  #include <sys/syscall.h>

>  

> +#if __INO_T_MATCHES_INO64_T

> +_Static_assert (sizeof (__blkcnt_t) == sizeof (__blkcnt64_t),

> +                "__blkcnt_t and __blkcnt64_t must match");

> +#endif


This isn't a good place for this check because this file is overridden for 
wordsize-32, meaning the check is missing in the wordsize-32 case.  It 
needs to go somewhere used whether or not the wordsize-32 subdirectory is 
in use.  (You could e.g. have a source file used only for this check, that 
compiles to an object file with no code.)

I think this assertion should also have a comment explaining that it's 
because the layout code in bits/stat.h, and the overflow handling in 
wordsize-32/overflow.h, require either all or none of the three types 
concerned to have padding.

-- 
Joseph S. Myers
joseph@codesourcery.com
Alistair Francis Oct. 18, 2019, 9:20 p.m. | #2
On Fri, Oct 18, 2019 at 8:08 AM Joseph Myers <joseph@codesourcery.com> wrote:
>

> On Wed, 16 Oct 2019, Alistair Francis wrote:

>

> > diff --git a/sysdeps/unix/sysv/linux/generic/xstat.c b/sysdeps/unix/sysv/linux/generic/xstat.c

> > index 75ceb9bc74b..ece14fc5838 100644

> > --- a/sysdeps/unix/sysv/linux/generic/xstat.c

> > +++ b/sysdeps/unix/sysv/linux/generic/xstat.c

> > @@ -28,6 +28,11 @@

> >  #include <sysdep.h>

> >  #include <sys/syscall.h>

> >

> > +#if __INO_T_MATCHES_INO64_T

> > +_Static_assert (sizeof (__blkcnt_t) == sizeof (__blkcnt64_t),

> > +                "__blkcnt_t and __blkcnt64_t must match");

> > +#endif

>

> This isn't a good place for this check because this file is overridden for

> wordsize-32, meaning the check is missing in the wordsize-32 case.  It

> needs to go somewhere used whether or not the wordsize-32 subdirectory is

> in use.  (You could e.g. have a source file used only for this check, that

> compiles to an object file with no code.)


Ok, I have added a file: sysdeps/unix/sysv/linux/generic/stat-check.c

>

> I think this assertion should also have a comment explaining that it's

> because the layout code in bits/stat.h, and the overflow handling in

> wordsize-32/overflow.h, require either all or none of the three types

> concerned to have padding.


Done!

Alistair

>

> --

> Joseph S. Myers

> joseph@codesourcery.com

Patch

diff --git a/sysdeps/unix/sysv/linux/generic/bits/stat.h b/sysdeps/unix/sysv/linux/generic/bits/stat.h
index 1565f3f8248..34c455ed786 100644
--- a/sysdeps/unix/sysv/linux/generic/bits/stat.h
+++ b/sysdeps/unix/sysv/linux/generic/bits/stat.h
@@ -42,7 +42,10 @@ 
 
 #if defined __USE_FILE_OFFSET64
 # define __field64(type, type64, name) type64 name
-#elif __WORDSIZE == 64
+#elif __WORDSIZE == 64 || defined __INO_T_MATCHES_INO64_T
+# if defined __INO_T_MATCHES_INO64_T && !defined __OFF_T_MATCHES_OFF64_T
+#  error "ino_t and off_t must both be the same type"
+# endif
 # define __field64(type, type64, name) type name
 #elif __BYTE_ORDER == __LITTLE_ENDIAN
 # define __field64(type, type64, name) \
diff --git a/sysdeps/unix/sysv/linux/generic/wordsize-32/overflow.h b/sysdeps/unix/sysv/linux/generic/wordsize-32/overflow.h
index 45efcd8fd34..66546b07ccd 100644
--- a/sysdeps/unix/sysv/linux/generic/wordsize-32/overflow.h
+++ b/sysdeps/unix/sysv/linux/generic/wordsize-32/overflow.h
@@ -36,12 +36,16 @@  static inline off_t lseek_overflow (loff_t res)
 
 static inline int stat_overflow (struct stat *buf)
 {
+#if defined __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.  */
diff --git a/sysdeps/unix/sysv/linux/generic/xstat.c b/sysdeps/unix/sysv/linux/generic/xstat.c
index 75ceb9bc74b..ece14fc5838 100644
--- a/sysdeps/unix/sysv/linux/generic/xstat.c
+++ b/sysdeps/unix/sysv/linux/generic/xstat.c
@@ -28,6 +28,11 @@ 
 #include <sysdep.h>
 #include <sys/syscall.h>
 
+#if __INO_T_MATCHES_INO64_T
+_Static_assert (sizeof (__blkcnt_t) == sizeof (__blkcnt64_t),
+                "__blkcnt_t and __blkcnt64_t must match");
+#endif
+
 /* Get information about the file NAME in BUF.  */
 int
 __xstat (int vers, const char *name, struct stat *buf)