@@ -802,8 +802,8 @@ pub(crate) fn utimensat(
802
802
flags : AtFlags ,
803
803
) -> io:: Result < ( ) > {
804
804
// Old 32-bit version: libc has `utimensat` but it is not y2038 safe by
805
- // default. But there may be a `__utimensat16 ` we can use.
806
- #[ cfg( fix_y2038) ]
805
+ // default. But there may be a `__utimensat64 ` we can use.
806
+ #[ cfg( all ( fix_y2038, not ( apple ) ) ) ]
807
807
{
808
808
#[ cfg( target_env = "gnu" ) ]
809
809
if let Some ( libc_utimensat) = __utimensat64. get ( ) {
@@ -874,6 +874,10 @@ pub(crate) fn utimensat(
874
874
) ) ;
875
875
}
876
876
877
+ // Convert `times`. We only need this in the child, but do it before
878
+ // calling `fork` because it might fail.
879
+ let ( attrbuf_size, times, attrs) = times_to_attrlist ( times) ?;
880
+
877
881
// `setattrlistat` was introduced in 10.13 along with `utimensat`, so
878
882
// if we don't have `utimensat`, we don't have `setattrlistat` either.
879
883
// Emulate it using `fork`, and `fchdir` and [`setattrlist`].
@@ -896,8 +900,6 @@ pub(crate) fn utimensat(
896
900
flags_arg |= FSOPT_NOFOLLOW ;
897
901
}
898
902
899
- let ( attrbuf_size, times, attrs) = times_to_attrlist ( times) ;
900
-
901
903
if setattrlist (
902
904
c_str ( path) ,
903
905
& attrs,
@@ -954,7 +956,7 @@ pub(crate) fn utimensat(
954
956
}
955
957
}
956
958
957
- #[ cfg( fix_y2038) ]
959
+ #[ cfg( all ( fix_y2038, not ( apple ) ) ) ]
958
960
fn utimensat_old (
959
961
dirfd : BorrowedFd < ' _ > ,
960
962
path : & CStr ,
@@ -1505,7 +1507,7 @@ fn libc_statvfs_to_statvfs(from: c::statvfs) -> StatVfs {
1505
1507
pub ( crate ) fn futimens ( fd : BorrowedFd < ' _ > , times : & Timestamps ) -> io:: Result < ( ) > {
1506
1508
// Old 32-bit version: libc has `futimens` but it is not y2038 safe by
1507
1509
// default. But there may be a `__futimens64` we can use.
1508
- #[ cfg( fix_y2038) ]
1510
+ #[ cfg( all ( fix_y2038, not ( apple ) ) ) ]
1509
1511
{
1510
1512
#[ cfg( target_env = "gnu" ) ]
1511
1513
if let Some ( libc_futimens) = __futimens64. get ( ) {
@@ -1556,7 +1558,7 @@ pub(crate) fn futimens(fd: BorrowedFd<'_>, times: &Timestamps) -> io::Result<()>
1556
1558
}
1557
1559
1558
1560
// Otherwise use `fsetattrlist`.
1559
- let ( attrbuf_size, times, attrs) = times_to_attrlist ( times) ;
1561
+ let ( attrbuf_size, times, attrs) = times_to_attrlist ( times) ? ;
1560
1562
1561
1563
ret ( fsetattrlist (
1562
1564
borrowed_fd ( fd) ,
@@ -1568,7 +1570,7 @@ pub(crate) fn futimens(fd: BorrowedFd<'_>, times: &Timestamps) -> io::Result<()>
1568
1570
}
1569
1571
}
1570
1572
1571
- #[ cfg( fix_y2038) ]
1573
+ #[ cfg( all ( fix_y2038, not ( apple ) ) ) ]
1572
1574
fn futimens_old ( fd : BorrowedFd < ' _ > , times : & Timestamps ) -> io:: Result < ( ) > {
1573
1575
let old_times = [
1574
1576
c:: timespec {
@@ -2125,7 +2127,7 @@ pub(crate) fn fcntl_global_nocache(fd: BorrowedFd<'_>, value: bool) -> io::Resul
2125
2127
/// Convert `times` from a `futimens`/`utimensat` argument into `setattrlist`
2126
2128
/// arguments.
2127
2129
#[ cfg( apple) ]
2128
- fn times_to_attrlist ( times : & Timestamps ) -> ( c:: size_t , [ c:: timespec ; 2 ] , Attrlist ) {
2130
+ fn times_to_attrlist ( times : & Timestamps ) -> io :: Result < ( c:: size_t , [ c:: timespec ; 2 ] , Attrlist ) > {
2129
2131
// ABI details.
2130
2132
const ATTR_CMN_MODTIME : u32 = 0x0000_0400 ;
2131
2133
const ATTR_CMN_ACCTIME : u32 = 0x0000_1000 ;
@@ -2134,7 +2136,8 @@ fn times_to_attrlist(times: &Timestamps) -> (c::size_t, [c::timespec; 2], Attrli
2134
2136
let mut times = times. clone ( ) ;
2135
2137
2136
2138
// If we have any `UTIME_NOW` elements, replace them with the current time.
2137
- if times. last_access . tv_nsec == c:: UTIME_NOW || times. last_modification . tv_nsec == c:: UTIME_NOW
2139
+ if times. last_access . tv_nsec == c:: UTIME_NOW . into ( )
2140
+ || times. last_modification . tv_nsec == c:: UTIME_NOW . into ( )
2138
2141
{
2139
2142
let now = {
2140
2143
let mut tv = c:: timeval {
@@ -2150,11 +2153,17 @@ fn times_to_attrlist(times: &Timestamps) -> (c::size_t, [c::timespec; 2], Attrli
2150
2153
tv_nsec : ( tv. tv_usec * 1000 ) as _ ,
2151
2154
}
2152
2155
} ;
2153
- if times. last_access . tv_nsec == c:: UTIME_NOW {
2154
- times. last_access = now;
2156
+ if times. last_access . tv_nsec == c:: UTIME_NOW . into ( ) {
2157
+ times. last_access = crate :: timespec:: Timespec {
2158
+ tv_sec : now. tv_sec . into ( ) ,
2159
+ tv_nsec : now. tv_nsec as _ ,
2160
+ } ;
2155
2161
}
2156
- if times. last_modification . tv_nsec == c:: UTIME_NOW {
2157
- times. last_modification = now;
2162
+ if times. last_modification . tv_nsec == c:: UTIME_NOW . into ( ) {
2163
+ times. last_modification = crate :: timespec:: Timespec {
2164
+ tv_sec : now. tv_sec . into ( ) ,
2165
+ tv_nsec : now. tv_nsec as _ ,
2166
+ } ;
2158
2167
}
2159
2168
}
2160
2169
@@ -2176,19 +2185,33 @@ fn times_to_attrlist(times: &Timestamps) -> (c::size_t, [c::timespec; 2], Attrli
2176
2185
tv_nsec : 0 ,
2177
2186
} ; 2 ] ;
2178
2187
let mut times_index = 0 ;
2179
- if times. last_modification . tv_nsec != c:: UTIME_OMIT {
2188
+ if times. last_modification . tv_nsec != c:: UTIME_OMIT . into ( ) {
2180
2189
attrs. commonattr |= ATTR_CMN_MODTIME ;
2181
- return_times[ times_index] = times. last_modification ;
2190
+ return_times[ times_index] = c:: timespec {
2191
+ tv_sec : times
2192
+ . last_modification
2193
+ . tv_sec
2194
+ . try_into ( )
2195
+ . map_err ( |_| io:: Errno :: OVERFLOW ) ?,
2196
+ tv_nsec : times. last_modification . tv_nsec as _ ,
2197
+ } ;
2182
2198
times_index += 1 ;
2183
2199
times_size += size_of :: < c:: timespec > ( ) ;
2184
2200
}
2185
- if times. last_access . tv_nsec != c:: UTIME_OMIT {
2201
+ if times. last_access . tv_nsec != c:: UTIME_OMIT . into ( ) {
2186
2202
attrs. commonattr |= ATTR_CMN_ACCTIME ;
2187
- return_times[ times_index] = times. last_access ;
2203
+ return_times[ times_index] = c:: timespec {
2204
+ tv_sec : times
2205
+ . last_access
2206
+ . tv_sec
2207
+ . try_into ( )
2208
+ . map_err ( |_| io:: Errno :: OVERFLOW ) ?,
2209
+ tv_nsec : times. last_access . tv_nsec as _ ,
2210
+ } ;
2188
2211
times_size += size_of :: < c:: timespec > ( ) ;
2189
2212
}
2190
2213
2191
- ( times_size, return_times, attrs)
2214
+ Ok ( ( times_size, return_times, attrs) )
2192
2215
}
2193
2216
2194
2217
/// Support type for `Attrlist`.
0 commit comments