@@ -336,19 +336,19 @@ inline void posix_unlinkat_impl(int dirfd, char const *path, int flags)
336336
337337namespace details
338338{
339- inline constexpr struct timespec unix_timestamp_to_struct_timespec64 (unix_timestamp stmp) noexcept
339+ inline constexpr struct timespec unix_timestamp_to_struct_timespec (unix_timestamp stmp) noexcept
340340{
341341 constexpr ::std::uint_least64_t mul_factor{uint_least64_subseconds_per_second / 1000000000u };
342342 return {static_cast <::std::time_t >(stmp.seconds ),
343- static_cast <long >(static_cast <long unsigned >(( stmp.subseconds ) / mul_factor))};
343+ static_cast <long >(static_cast <long unsigned >(stmp.subseconds / mul_factor))};
344344}
345345
346346inline
347347#if defined(UTIME_NOW) && defined(UTIME_OMIT)
348348 constexpr
349349#endif
350350 struct timespec
351- unix_timestamp_to_struct_timespec64 ([[maybe_unused]] unix_timestamp_option opt) noexcept
351+ unix_timestamp_to_struct_timespec ([[maybe_unused]] unix_timestamp_option opt) noexcept
352352{
353353#if defined(UTIME_NOW) && defined(UTIME_OMIT)
354354 switch (opt.flags )
@@ -357,13 +357,52 @@ inline
357357 return {.tv_sec = 0 , .tv_nsec = UTIME_NOW };
358358 case utime_flags::omit:
359359 return {.tv_sec = 0 , .tv_nsec = UTIME_OMIT };
360+ default :
361+ return unix_timestamp_to_struct_timespec (opt.timestamp );
362+ }
363+ #else
364+ throw_posix_error (EINVAL );
365+ #endif
366+ }
367+
368+ #if defined(__linux__) && defined(__NR_utimensat_time64)
369+
370+ // https://github.com/torvalds/linux/blob/07e27ad16399afcd693be20211b0dfae63e0615f/include/uapi/linux/time_types.h#L7
371+ struct kernel_timespec64
372+ {
373+ ::std::int_least64_t tv_sec;
374+ ::std::int_least64_t tv_nsec;
375+ };
376+
377+ inline constexpr kernel_timespec64 unix_timestamp_to_struct_timespec64 (unix_timestamp stmp) noexcept
378+ {
379+ constexpr ::std::uint_least64_t mul_factor{uint_least64_subseconds_per_second / 1000000000u };
380+ return {static_cast <::std::int_least64_t >(stmp.seconds ),
381+ static_cast <::std::int_least64_t >(stmp.subseconds / mul_factor)};
382+ }
383+
384+ inline
385+ #if defined(UTIME_NOW) && defined(UTIME_OMIT)
386+ constexpr
387+ #endif
388+ kernel_timespec64
389+ unix_timestamp_to_struct_timespec64 ([[maybe_unused]] unix_timestamp_option opt) noexcept
390+ {
391+ #if defined(UTIME_NOW) && defined(UTIME_OMIT)
392+ switch (opt.flags )
393+ {
394+ case utime_flags::now:
395+ return {.tv_sec = 0 , .tv_nsec = static_cast <::std::int_least64_t >(UTIME_NOW )};
396+ case utime_flags::omit:
397+ return {.tv_sec = 0 , .tv_nsec = static_cast <::std::int_least64_t >(UTIME_OMIT )};
360398 default :
361399 return unix_timestamp_to_struct_timespec64 (opt.timestamp );
362400 }
363401#else
364402 throw_posix_error (EINVAL );
365403#endif
366404}
405+ #endif
367406
368407} // namespace details
369408
@@ -375,11 +414,21 @@ inline void posix_utimensat_impl(int dirfd, char const *path, unix_timestamp_opt
375414 {
376415 throw_posix_error (EINVAL );
377416 }
378- struct timespec ts[2 ]{
417+
418+ #if defined(__linux__) && defined(__NR_utimensat_time64)
419+ details::kernel_timespec64 ts[2 ]{
379420 details::unix_timestamp_to_struct_timespec64 (last_access_time),
380421 details::unix_timestamp_to_struct_timespec64 (last_modification_time),
381422 };
423+ details::kernel_timespec64 *tsptr{ts};
424+ #else
425+ struct timespec ts[2 ]{
426+ details::unix_timestamp_to_struct_timespec (last_access_time),
427+ details::unix_timestamp_to_struct_timespec (last_modification_time),
428+ };
382429 struct timespec *tsptr{ts};
430+ #endif
431+
383432 system_call_throw_error (
384433#if defined(__linux__)
385434#if defined(__NR_utimensat_time64)
0 commit comments