[RFC 3/6] y2038: Export struct_stat_time64_helper.h with Y2038 safe stat{64} content

Lukasz Majewski lukma@denx.de
Tue Dec 29 10:30:49 GMT 2020


Dear Community,

> This patch exports fields of y2038 safe members of struct stat when
> -D_TIME_BITS=64 is passed as compilation flag.
> 
> Such approach will allow avoiding many copies of the same structure
> for several other architectures.
> 
> It was also necessary to redefine some parts of this structure for
> the glibc internal struct __stat64_t64 as the struct __timespec64
> is not exported and only used locally in the glibc.
> 
> Exported, port specific (with __WORDSIZE=32 && __TIMESIZE!=64),
> struct stat has been modified to support 64 bit time as well.

I would like to ask for review on this patch, as it is crucial for 64
bit stat support on ports with __WORDSIZE != 64 && _TIMESIZE==32.

It shall not bring any issues untill __USE_TIME_BITS64 is defined.

> ---
>  sysdeps/unix/sysv/linux/Makefile              |  3 +-
>  sysdeps/unix/sysv/linux/bits/struct_stat.h    | 17 ++++-
>  .../linux/bits/struct_stat_time64_helper.h    | 70
> +++++++++++++++++++ .../unix/sysv/linux/m68k/bits/struct_stat.h   |
> 16 +++++ .../sysv/linux/microblaze/bits/struct_stat.h  | 16 +++++
>  .../unix/sysv/linux/mips/bits/struct_stat.h   | 16 +++++
>  .../sysv/linux/powerpc/bits/struct_stat.h     | 48 ++++++++-----
>  sysdeps/unix/sysv/linux/struct_stat_time64.h  | 60 +++-------------
>  .../unix/sysv/linux/x86/bits/struct_stat.h    | 16 +++++
>  9 files changed, 194 insertions(+), 68 deletions(-)
>  create mode 100644
> sysdeps/unix/sysv/linux/bits/struct_stat_time64_helper.h
> 
> diff --git a/sysdeps/unix/sysv/linux/Makefile
> b/sysdeps/unix/sysv/linux/Makefile index 09604e128b..2d5cf9bf09 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -97,7 +97,8 @@ sysdep_headers += sys/mount.h sys/acct.h \
>  		  bits/types/struct_msqid_ds.h \
>  		  bits/types/struct_shmid_ds.h \
>  		  bits/ipc-perm.h \
> -		  bits/struct_stat.h
> +		  bits/struct_stat.h \
> +		  bits/struct_stat_time64_helper.h
>  
>  tests += tst-clone tst-clone2 tst-clone3 tst-fanotify
> tst-personality \ tst-quota tst-sync_file_range tst-sysconf-iov_max
> tst-ttyname \ diff --git a/sysdeps/unix/sysv/linux/bits/struct_stat.h
> b/sysdeps/unix/sysv/linux/bits/struct_stat.h index
> 344bffece6..6dd7aeffcf 100644 ---
> a/sysdeps/unix/sysv/linux/bits/struct_stat.h +++
> b/sysdeps/unix/sysv/linux/bits/struct_stat.h @@ -26,6 +26,13 @@
>  #include <bits/endian.h>
>  #include <bits/wordsize.h>
>  
> +#ifdef __USE_TIME_BITS64
> +# include <bits/struct_stat_time64_helper.h>
> +struct stat
> +  {
> +    __STAT64_T64_CONTENT
> +  };
> +#else
>  struct stat
>    {
>      __dev_t st_dev;			/* Device.  */
> @@ -81,8 +88,16 @@ struct stat
>      __ino64_t st_ino;			/* File serial
> number.	*/ #endif
>    };
> +#endif /* __USE_TIME_BITS64  */
>  
>  #ifdef __USE_LARGEFILE64
> +# ifdef __USE_TIME_BITS64
> +# include <bits/struct_stat_time64_helper.h>
> +struct stat64
> +  {
> +    __STAT64_T64_CONTENT
> +  };
> +# else
>  struct stat64
>    {
>      __dev_t st_dev;			/* Device.  */
> @@ -119,6 +134,7 @@ struct stat64
>  # endif
>      __ino64_t st_ino;			/* File serial
> number.		*/ };
> +# endif /* __USE_TIME_BITS64  */
>  #endif
>  
>  /* Tell code we have these members.  */
> @@ -127,5 +143,4 @@ struct stat64
>  /* Nanosecond resolution time values are supported.  */
>  #define _STATBUF_ST_NSEC
>  
> -
>  #endif /* _BITS_STRUCT_STAT_H  */
> diff --git a/sysdeps/unix/sysv/linux/bits/struct_stat_time64_helper.h
> b/sysdeps/unix/sysv/linux/bits/struct_stat_time64_helper.h new file
> mode 100644 index 0000000000..3ca6258bd5
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/bits/struct_stat_time64_helper.h
> @@ -0,0 +1,70 @@
> +/* Definition for helper to define struct stat with 64 bit time.
> +   Copyright (C) 2020 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be
> useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _BITS_STRUCT_STAT_TIME64_HELPER_H
> +#define _BITS_STRUCT_STAT_TIME64_HELPER_H	1
> +
> +#include <bits/endian.h>
> +
> +/* The definition should be equal to the 'struct __timespec64'
> internal
> +   layout.  */
> +#if BYTE_ORDER == BIG_ENDIAN
> +# define __fieldts64(name)					\
> +     __time64_t name; __int32_t :32; __int32_t name ## nsec
> +#else
> +# define __fieldts64(name)					\
> +     __time64_t name; __int32_t name ## nsec; __int32_t :32
> +#endif
> +
> +# ifdef __USE_XOPEN2K8
> +# define st_atime st_atim.tv_sec
> +# define st_mtime st_mtim.tv_sec
> +# define st_ctime st_ctim.tv_sec
> +    /* Nanosecond resolution timestamps are stored in a format
> +       equivalent to 'struct timespec'.  This is the type used
> +       whenever possible but the Unix namespace rules do not allow
> the
> +       identifier 'timespec' to appear in the <sys/stat.h> header.
> +       Therefore we have to handle the use of this header in strictly
> +       standard-compliant sources special.  */
> +#  define __STAT64_TIME64_CONTENT  \
> +    struct timespec st_atim; \
> +    struct timespec st_mtim; \
> +    struct timespec st_ctim;
> +# else
> +#  define __STAT64_TIME64_CONTENT  \
> +	__fieldts64 (st_atime); \
> +	__fieldts64 (st_mtime); \
> +	__fieldts64 (st_ctime);
> +# endif /* __USE_XOPEN2K8  */
> +
> +/* Content of internal __stat64_t64 struct.  */
> +#define __STAT64_T64_CONTENT
>           \
> +    __dev_t st_dev;			/* Device.  */
>              \
> +    __ino64_t st_ino;			/* file serial
> number.	*/             \
> +    __mode_t st_mode;			/* File mode.  */
>                \
> +    __nlink_t st_nlink;			/* Link count.  */
>          \
> +    __uid_t st_uid;			/* User ID of the file's
> owner.  */    \
> +    __gid_t st_gid;			/* Group ID of the file's
> group.*/     \
> +    __dev_t st_rdev;			/* Device number, if
> device.  */       \
> +    __off64_t st_size;			/* Size of file, in
> bytes.  */         \
> +    __blksize_t st_blksize;		/* Optimal block size for
> I/O.  */     \
> +    __blkcnt64_t st_blocks;		/* Number 512-byte blocks
> allocated. */\
> +    __STAT64_TIME64_CONTENT
> +
> +# undef __fieldts64
> +#endif /* _BITS_STRUCT_STAT_TIME64_HELPER_H  */
> diff --git a/sysdeps/unix/sysv/linux/m68k/bits/struct_stat.h
> b/sysdeps/unix/sysv/linux/m68k/bits/struct_stat.h index
> bf457a0db7..5bf9e110fb 100644 ---
> a/sysdeps/unix/sysv/linux/m68k/bits/struct_stat.h +++
> b/sysdeps/unix/sysv/linux/m68k/bits/struct_stat.h @@ -23,6 +23,13 @@
>  #ifndef _BITS_STRUCT_STAT_H
>  #define _BITS_STRUCT_STAT_H	1
>  
> +#ifdef __USE_TIME_BITS64
> +# include <bits/struct_stat_time64_helper.h>
> +struct stat
> +  {
> +    __STAT64_T64_CONTENT
> +  };
> +#else
>  struct stat
>    {
>      __dev_t st_dev;			/* Device.  */
> @@ -78,8 +85,16 @@ struct stat
>      __ino64_t st_ino;			/* File serial
> number.	*/ #endif
>    };
> +#endif /* __USE_TIME_BITS64 */
>  
>  #ifdef __USE_LARGEFILE64
> +# ifdef __USE_TIME_BITS64
> +# include <bits/struct_stat_time64_helper.h>
> +struct stat64
> +  {
> +    __STAT64_T64_CONTENT
> +  };
> +# else
>  struct stat64
>    {
>      __dev_t st_dev;			/* Device.  */
> @@ -116,6 +131,7 @@ struct stat64
>  # endif
>      __ino64_t st_ino;			/* File serial
> number.		*/ };
> +# endif /* __USE_TIME_BITS64 */
>  #endif
>  
>  /* Tell code we have these members.  */
> diff --git a/sysdeps/unix/sysv/linux/microblaze/bits/struct_stat.h
> b/sysdeps/unix/sysv/linux/microblaze/bits/struct_stat.h index
> db81543b23..3fac74039a 100644 ---
> a/sysdeps/unix/sysv/linux/microblaze/bits/struct_stat.h +++
> b/sysdeps/unix/sysv/linux/microblaze/bits/struct_stat.h @@ -63,6
> +63,13 @@ struct stat unsigned int            __glibc_reserved5;
>  };
>  #else /* __USE_FILE_OFFSET64 */
> +# ifdef __USE_TIME_BITS64
> +#  include <bits/struct_stat_time64_helper.h>
> +struct stat
> +  {
> +    __STAT64_T64_CONTENT
> +  };
> +# else
>  /* MS: If __USE_FILE_OFFSET64 is setup then struct stat should match
> stat64
>   * structure. Glibc has no type __dev64_t that's why I had to use
> standard
>   * type for st_dev and st_rdev. Several architectures uses pads
> after st_dev @@ -106,9 +113,17 @@ struct stat
>          unsigned int            __glibc_reserved4;
>          unsigned int            __glibc_reserved5;
>  };
> +# endif /* __USE_TIME_BITS64 */
>  #endif /* __USE_FILE_OFFSET64 */
>  
>  #ifdef __USE_LARGEFILE64
> +# ifdef __USE_TIME_BITS64
> +# include <bits/struct_stat_time64_helper.h>
> +struct stat64
> +  {
> +    __STAT64_T64_CONTENT
> +  };
> +# else
>  struct stat64
>  {
>          unsigned long long      st_dev;     /* Device.  */
> @@ -147,6 +162,7 @@ struct stat64
>          unsigned int            __glibc_reserved4;
>          unsigned int            __glibc_reserved5;
>  };
> +# endif /* __USE_TIME_BITS64 */
>  #endif
>  
>  /* Tell code we have these members.  */
> diff --git a/sysdeps/unix/sysv/linux/mips/bits/struct_stat.h
> b/sysdeps/unix/sysv/linux/mips/bits/struct_stat.h index
> 5abd71fc23..0b88f7cba5 100644 ---
> a/sysdeps/unix/sysv/linux/mips/bits/struct_stat.h +++
> b/sysdeps/unix/sysv/linux/mips/bits/struct_stat.h @@ -119,6 +119,13
> @@ struct stat64 };
>  #endif
>  #else
> +# ifdef __USE_TIME_BITS64
> +#  include <bits/struct_stat_time64_helper.h>
> +struct stat
> +  {
> +    __STAT64_T64_CONTENT
> +  };
> +# else
>  struct stat
>    {
>      __dev_t st_dev;
> @@ -171,8 +178,16 @@ struct stat
>  #endif
>      int st_pad5[14];
>    };
> +# endif /* __USE_TIME_BITS64 */
>  
>  #ifdef __USE_LARGEFILE64
> +# ifdef __USE_TIME_BITS64
> +# include <bits/struct_stat_time64_helper.h>
> +struct stat64
> +  {
> +    __STAT64_T64_CONTENT
> +  };
> +# else
>  struct stat64
>    {
>      __dev_t st_dev;
> @@ -208,6 +223,7 @@ struct stat64
>      __blkcnt64_t st_blocks;
>      int st_pad4[14];
>  };
> +# endif /* __USE_TIME_BITS64 */
>  #endif
>  #endif
>  
> diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/struct_stat.h
> b/sysdeps/unix/sysv/linux/powerpc/bits/struct_stat.h index
> cb41adc7c0..09228e046e 100644 ---
> a/sysdeps/unix/sysv/linux/powerpc/bits/struct_stat.h +++
> b/sysdeps/unix/sysv/linux/powerpc/bits/struct_stat.h @@ -26,35 +26,41
> @@ #include <bits/wordsize.h>
>  
>  #if __WORDSIZE == 32
> -
> +# ifdef __USE_TIME_BITS64
> +# include <bits/struct_stat_time64_helper.h>
> +struct stat
> +  {
> +    __STAT64_T64_CONTENT
> +  };
> +# else
>  struct stat
>    {
>      __dev_t st_dev;			/* Device.  */
> -# ifndef __USE_FILE_OFFSET64
> +#  ifndef __USE_FILE_OFFSET64
>      unsigned short int __pad1;
>      __ino_t st_ino;			/* File serial
> number.	*/ -# else
> +#  else
>      __ino64_t st_ino;			/* File serial
> number.	*/ -# endif
> +#  endif
>      __mode_t st_mode;			/* File mode.  */
>      __nlink_t st_nlink;			/* Link count.  */
>      __uid_t st_uid;			/* User ID of the file's
> owner.	*/ __gid_t st_gid;			/* Group ID
> of the file's group.*/ __dev_t st_rdev;			/*
> Device number, if device.  */ unsigned short int __pad2;
> -# ifndef __USE_FILE_OFFSET64
> +#  ifndef __USE_FILE_OFFSET64
>      __off_t st_size;			/* Size of file, in
> bytes.  */ -# else
> +#  else
>      __off64_t st_size;			/* Size of file, in
> bytes.  */ -# endif
> +#  endif
>      __blksize_t st_blksize;		/* Optimal block size for
> I/O.  */ 
> -# ifndef __USE_FILE_OFFSET64
> +#  ifndef __USE_FILE_OFFSET64
>      __blkcnt_t st_blocks;		/* Number 512-byte blocks
> allocated. */ -# else
> +#  else
>      __blkcnt64_t st_blocks;		/* Number 512-byte blocks
> allocated. */ -# endif
> -# ifdef __USE_XOPEN2K8
> +#  endif
> +#  ifdef __USE_XOPEN2K8
>      /* Nanosecond resolution timestamps are stored in a format
>         equivalent to 'struct timespec'.  This is the type used
>         whenever possible but the Unix namespace rules do not allow
> the @@ -64,23 +70,30 @@ struct stat
>      struct timespec st_atim;		/* Time of last access.
> */ struct timespec st_mtim;		/* Time of last
> modification.  */ struct timespec st_ctim;		/* Time of
> last status change.  */ -#  define st_atime st_atim.tv_sec	/*
> Backward compatibility.  */ -#  define st_mtime st_mtim.tv_sec
> -#  define st_ctime st_ctim.tv_sec
> -# else
> +#   define st_atime st_atim.tv_sec	/* Backward compatibility.
>  */ +#   define st_mtime st_mtim.tv_sec
> +#   define st_ctime st_ctim.tv_sec
> +#  else
>      __time_t st_atime;			/* Time of last
> access.  */ unsigned long int st_atimensec;	/* Nscecs of last
> access.  */ __time_t st_mtime;			/* Time of last
> modification.  */ unsigned long int st_mtimensec;	/* Nsecs of
> last modification.  */ __time_t st_ctime;			/*
> Time of last status change.  */ unsigned long int
> st_ctimensec;	/* Nsecs of last status change.  */ -# endif
> +#  endif
>      unsigned long int __glibc_reserved4;
>      unsigned long int __glibc_reserved5;
>    };
> -
> +# endif /* __USE_TIME_BITS64 */
>  
>  # ifdef __USE_LARGEFILE64
> +#  ifdef __USE_TIME_BITS64
> +#  include <bits/struct_stat_time64_helper.h>
> +struct stat64
> +  {
> +    __STAT64_T64_CONTENT
> +  };
> +#  else
>  struct stat64
>    {
>      __dev_t st_dev;			/* Device.  */
> @@ -213,6 +226,7 @@ struct stat64
>      unsigned long int __glibc_reserved5;
>      unsigned long int __glibc_reserved6;
>    };
> +#  endif /* __USE_TIME_BITS64 */
>  # endif /* __USE_LARGEFILE64 */
>  #endif
>  
> diff --git a/sysdeps/unix/sysv/linux/struct_stat_time64.h
> b/sysdeps/unix/sysv/linux/struct_stat_time64.h index
> b85385b6f3..5a4949000e 100644 ---
> a/sysdeps/unix/sysv/linux/struct_stat_time64.h +++
> b/sysdeps/unix/sysv/linux/struct_stat_time64.h @@ -23,63 +23,25 @@
>  # define __stat64_t64 stat64
>  #else
>  # ifdef __USE_LARGEFILE64
> -#  include <endian.h>
> -
> -/* The definition should be equal to the 'struct __timespec64'
> internal
> -   layout.  */
> -#  if BYTE_ORDER == BIG_ENDIAN
> -#   define __fieldts64(name)
> \
> -     __time64_t name; __int32_t :32; __int32_t name ## nsec
> -#  else
> -#   define __fieldts64(name)					\
> -     __time64_t name; __int32_t name ## nsec; __int32_t :32
> -#  endif
> -
> -/* Workaround for the definition from struct_stat.h  */
> -#  undef st_atime
> -#  undef st_mtime
> -#  undef st_ctime
> -
> +#  include <struct___timespec64.h>
> +#  include <bits/struct_stat_time64_helper.h>
> +#  ifdef __USE_XOPEN2K8
> +#   undef __STAT64_TIME64_CONTENT
> +/* Use glibc internal types for time related members */
> +#   define __STAT64_TIME64_CONTENT  \
> +      struct __timespec64 st_atim; \
> +      struct __timespec64 st_mtim; \
> +      struct __timespec64 st_ctim;
> +#  endif /* __USE_XOPEN2K8 */
>  struct __stat64_t64
>    {
> -    __dev_t st_dev;			/* Device.  */
> -    __ino64_t st_ino;			/* file serial
> number.	*/
> -    __mode_t st_mode;			/* File mode.  */
> -    __nlink_t st_nlink;			/* Link count.  */
> -    __uid_t st_uid;			/* User ID of the file's
> owner.	*/
> -    __gid_t st_gid;			/* Group ID of the file's
> group.*/
> -    __dev_t st_rdev;			/* Device number, if
> device.  */
> -    __off64_t st_size;			/* Size of file, in
> bytes.  */
> -    __blksize_t st_blksize;		/* Optimal block size for
> I/O.  */
> -    __blkcnt64_t st_blocks;		/* Number 512-byte blocks
> allocated. */ -#   ifdef __USE_XOPEN2K8
> -    /* Nanosecond resolution timestamps are stored in a format
> -       equivalent to 'struct timespec'.  This is the type used
> -       whenever possible but the Unix namespace rules do not allow
> the
> -       identifier 'timespec' to appear in the <sys/stat.h> header.
> -       Therefore we have to handle the use of this header in strictly
> -       standard-compliant sources special.  */
> -    struct __timespec64 st_atim;	/* Time of last access.  */
> -    struct __timespec64 st_mtim;	/* Time of last
> modification.  */
> -    struct __timespec64 st_ctim;	/* Time of last status
> change.  */ -#    define st_atime st_atim.tv_sec	/* Backward
> compatibility.  */ -#    define st_mtime st_mtim.tv_sec
> -#    define st_ctime st_ctim.tv_sec
> -#   else
> -    __fieldts64 (st_atime);
> -    __fieldts64 (st_mtime);
> -    __fieldts64 (st_ctime);
> -#   endif /* __USE_XOPEN2K8  */
> +    __STAT64_T64_CONTENT
>    };
>  
>  #   define _STATBUF_ST_BLKSIZE
>  #   define _STATBUF_ST_RDEV
>  #   define _STATBUF_ST_NSEC
>  
> -#   undef __fieldts64
> -
>  #  endif /* __USE_LARGEFILE64  */
> -
>  # endif /* __TIMESIZE == 64  */
> -
>  #endif /* _BITS_STRUCT_STAT_TIME64_H  */
> diff --git a/sysdeps/unix/sysv/linux/x86/bits/struct_stat.h
> b/sysdeps/unix/sysv/linux/x86/bits/struct_stat.h index
> dae7aa46b3..e7e87c62b4 100644 ---
> a/sysdeps/unix/sysv/linux/x86/bits/struct_stat.h +++
> b/sysdeps/unix/sysv/linux/x86/bits/struct_stat.h @@ -23,6 +23,13 @@
>  #ifndef _BITS_STRUCT_STAT_H
>  #define _BITS_STRUCT_STAT_H	1
>  
> +#ifdef __USE_TIME_BITS64
> +# include <bits/struct_stat_time64_helper.h>
> +struct stat
> +  {
> +    __STAT64_T64_CONTENT
> +  };
> +#else
>  struct stat
>    {
>      __dev_t st_dev;		/* Device.  */
> @@ -93,9 +100,17 @@ struct stat
>  # endif
>  #endif
>    };
> +#endif /* __USE_TIME_BITS64 */
>  
>  #ifdef __USE_LARGEFILE64
>  /* Note stat64 has the same shape as stat for x86-64.  */
> +# ifdef __USE_TIME_BITS64
> +# include <bits/struct_stat_time64_helper.h>
> +struct stat64
> +  {
> +    __STAT64_T64_CONTENT
> +  };
> +# else
>  struct stat64
>    {
>      __dev_t st_dev;		/* Device.  */
> @@ -146,6 +161,7 @@ struct stat64
>      __ino64_t st_ino;			/* File serial
> number.		*/ # endif
>    };
> +# endif /* __USE_TIME_BITS64  */
>  #endif
>  
>  /* Tell code we have these members.  */




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <https://sourceware.org/pipermail/libc-alpha/attachments/20201229/47d86c10/attachment.sig>


More information about the Libc-alpha mailing list