[PATCH] y2038: Reorder placement of st_ino in struct __stat64_t64
Adhemerval Zanella
adhemerval.zanella@linaro.org
Thu Oct 15 11:03:28 GMT 2020
On 14/10/2020 19:00, Lukasz Majewski wrote:
> Hi Adhemerval,
>
>> On 14/10/2020 12:56, Lukasz Majewski wrote:
>>> Hi Adhemerval,
>>>
>>>> On 14/10/2020 11:14, Lukasz Majewski wrote:
>>>>> Hi Adhemerval,
>>>>>
>>>>>> On 14/10/2020 10:00, Lukasz Majewski wrote:
>>>>>>> In the installed struct stat{64} the __ino64_t st_ino member is
>>>>>>> placed in the end. This patch moves it to the same position as
>>>>>>> in the aforementioned, exported structures as it allows less
>>>>>>> #ifdefs for __USE_TIME_BITS64 support use case.
>>>>>>
>>>>>> Why exactly this is required? Afaik this is glibc defined type
>>>>>> not currently only used internally and all member accesses are
>>>>>> set directly (no use or memcpy or offsetof). Is this related to
>>>>>> the issue you saw on the arm environment?
>>>>>
>>>>> This is required to make the minimal changes to provide
>>>>> -D_TIME_SIZE=64 support for {f}stat{at} as in:
>>>>> https://github.com/lmajewski/y2038_glibc/commit/26aa2ac07246682a505d85dac1c269689964b79b
>>>>>
>>>>
>>>> But the idea it to decouple y2038 stat from the generic stat which
>>>> support non-LFS and make it support solely LFS.
>>>
>>> And this idea is correct.
>>>
>>>> As Joseph has pointed
>>>> out, the __stat64_t64 should be architecture-independent and I
>>>> think it simplifies its definition to untie from struct_stat.h
>>>> (which has multiple definitions due historically each architecture
>>>> to tie with the selected kernel ABI).
>>>
>>> This is also correct assumption.
>>>
>>> Please find my explanation of the problem as I may not been
>>> correctly understood:
>>>
>>> For example the __fstat64_time64 defined in
>>> sysdeps/unix/sysv/linux/fstat64.c has following signature:
>>>
>>> int __fstat64_time64 (int fd, struct __stat64_t64 *buf)
>>>
>>> for:
>>> - __WORDSIZE==64 is struct __stat64_t64 is aliased to struct
>>> stat64,
>>
>> Not __WORDSIZE==64 but rather XSTAT_IS_XSTAT64, since mips64 and
>> mips64-n32 provides non-LFS interfaces. For XSTAT_IS_XSTAT64 ABIs,
>> __stat64_t64 is also essentially stat and the {f,l}stat{at}64 is
>> aliased to {f,l}stat{at}.
>
> Ok.
>
>>
>>> - __WORDSIZE==32 (Non Y2038) uses __fstat64 with struct stat64
>>> - __WORDSIZE==32 (Y2038) will redirect fstat calls to
>>> __fstat64_time64 and as a result it will have to accept *buf which
>>> must be binary compatible with struct stat{64} and __stat64_t64.
>>
>> Yes, fstat on __WORDSIZE==32 with XSTAT_IS_XSTAT64 will be an alias
>> to __fstat64_time64 (and this now assumed that any new 32-bit ABI
>> will have to only provide LFS interfaces and 64-bit time_t).
>
> I do agree.
>
>>
>> Also for such cases __stat64_t64 *won't* be exported, its struct stat
>> *already* has 64-bit time fields.
>
> Yes, correct.
>
>>
>>>
>>> By binary compatible I mean the layout and fields must be identical
>>> as passing struct stat{64} to __fstat64_time64 will force casting
>>> of the data pointed by *buf.
>>
>> I think there is a confusion here, for currently y2038 enabled ABIs
>> you will have either the first situation or the second you described.
>>
>> For future y2038 ABIs (basically all 32-bit that still supports
>> 32-bit time_t) __stat64_t64 and stat64 do *not* require to be binary
>> compatible.
>
> Hmm....
>
>>
>> In this case you will have:
>>
>> 1. non-LFS {f,l}stat{64} that accepts 'struct stat'.
>
> By LFS I guess you mean the -D_LARGEFILE64_SOURCE compilation switch
> (which is optional and enables struct stat64 support).
>
>> 2. LFS with 32-bit time fields {f,l}stat{64} that accepts 'struct
>> stat64'.
>
> Is this scenario valid? For Y2038 support on ARM usage of
> -D_TIME_BITS=64 also mandatory implies -D_FILE_OFFSET_BITS=64
Yes, this scenario is still valid since we have not deprecated non-LFS
call. Recall that no non-LFS 64-bit time is *not* supported.
>
>> 3. LFS with 64-bit time fields {f,l}fstat64_t64 (or any other
>> name for the exported ABI) with accepts 'struct __stat64_t64'.
>
> Ok. This is the case on which I'm working on.
>
>>
>> This is *different* than the current 32-bit y2038 enabled ABIs
>> (arc, riscv32) which does not need to support neither 1. nor 2..
>
> Ok. I know. Let's keep it aside as they support LFS and Y2038 from the
> outset.
>
>> For this architecture the exported ABI is similar to current majority
>> 64-bit architectures (modules mips64...), where they exports
>> {f,l}stat{at} with {f,l}stat{at}{64} being just aliases.
>
> Ok.
>
>>
>> So for instance on ARM, to actually use the y2038 calls we will need
>> to export the __{f,l}stat{at}64_time64 along with the 'struct
>> __stat64_t64' *and* redirects the LFS calls {f,l}stat{at}64 calls to
>> _{f,l}stat{at}64_time64 for _TIME_BITS=64
>
> I think I'm following the above guidelines in my WIP patch, which adds
> support for -D_TIME_BITS=64.
>
>> (along with redefine the
>> 'struct stat64' to 'struct __stat64_t64').
>
> Please correct me if I'm wrong, but I shall be doable to:
> (in unix/sysv/linux/bits/struct_stat.h)
>
> #ifdef __USE_TIME_BITS64
> # include <struct_stat_time64.h>
> # define stat __stat64_t64
> #else
> struct stat
> {
> ...
> }
> #endif /* __USE_TIME_BITS64 */
>
>
> And the same pattern for struct stat64.
What I think what needs to be done is:
1. Move sysdeps/unix/sysv/linux/struct_stat_time64.h to
sysdeps/unix/sysv/linux/bits/struct_stat_time64.h and adds it on
sysdep_headeps at sysdeps/unix/sysv/linux/Makefile. This will instruct to
install the header.
2. Either on sysdeps/unix/sysv/linux/bits/stat.h or
unix/sysv/linux/bits/struct_stat.h include the struct_stat_time64.h
for __USE_TIME_BITS64. I do not have strong preference here, but I think
adding of unix/sysv/linux/bits/struct_stat.h results in less nesting and
simplify things a bit.
3. On io/sys/stat.h add the logic to redirect to the y2038 implementations:
---
#ifndef __USE_FILE_OFFSET64
/* Get file attributes for FILE and put them in BUF. */
extern int stat (const char *__restrict __file,
struct stat *__restrict __buf) __THROW __nonnull ((1, 2));
/* Get file attributes for the file, device, pipe, or socket
that file descriptor FD is open on and put them in BUF. */
extern int fstat (int __fd, struct stat *__buf) __THROW __nonnull ((2));
#else
# ifdef __USE_TIME_BITS64
# ifdef __REDIRECT_NTH
extern int __REDIRECT_NTH (stat, (const char *__restrict __file,
struct __stat64_t64 *__restrict __buf), __stat64_t64)
__nonnull ((1, 2));
extern int __REDIRECT_NTH (fstat, (int __fd, struct __stat64_t64 *__buf), __fstat64_t64)
__nonnull ((2));
# else
# define stat64 __stat64_t64
# define fstat64 __fstat64_t64
# endif /* __REDIRECT_NTH */
# else
# ifdef __REDIRECT_NTH
extern int __REDIRECT_NTH (stat, (const char *__restrict __file,
struct stat *__restrict __buf), stat64)
__nonnull ((1, 2));
extern int __REDIRECT_NTH (fstat, (int __fd, struct stat *__buf), fstat64)
__nonnull ((2));
# else
# define stat stat64
# define fstat fstat64
# endif /* __REDIRECT_NTH */
# endif /* __USE_TIME_BITS64 */
#endif
#ifdef __USE_LARGEFILE64
# ifdef __USE_TIME_BITS64
extern int __REDIRECT_NTH (stat64, (const char *__restrict __file,
struct __stat64_t64 *__restrict __buf), __stat64_t64)
__nonnull ((1, 2));
extern int __REDIRECT_NTH (fstat64, (int __fd, struct __stat64_t64 *__buf), __fstat64_t64)
__nonnull ((2));
# else
extern int stat64 (const char *__restrict __file,
struct stat64 *__restrict __buf) __THROW __nonnull ((1, 2));
extern int fstat64 (int __fd, struct stat64 *__buf) __THROW __nonnull ((2));
# endif /* __USE_TIME_BITS64 */
#endif
---
So y2038 safe interfaces will be used only if both __USE_FILE_OFFSET64 and
__USE_TIME_BITS64 are defined. What I am not sure if we should also need to
export the y2038 interfaces for _LARGEFILE64_SOURCE.
I haven't tested it, so you would want to check if something is missing for
64-bit architectures with current 64-bit time support to see if it misses
something. We need to handle it to *not* redirect to the __{f}stat64_t64
interfaces, so maybe it should be a more complex ifdef definitions.
More information about the Libc-alpha
mailing list