@@ -1604,24 +1604,6 @@ impl File {
16041604 }
16051605
16061606 pub fn set_times ( & self , times : FileTimes ) -> io:: Result < ( ) > {
1607- #[ cfg( not( any(
1608- target_os = "redox" ,
1609- target_os = "espidf" ,
1610- target_os = "horizon" ,
1611- target_os = "nuttx" ,
1612- ) ) ) ]
1613- let to_timespec = |time : Option < SystemTime > | match time {
1614- Some ( time) if let Some ( ts) = time. t . to_timespec ( ) => Ok ( ts) ,
1615- Some ( time) if time > crate :: sys:: time:: UNIX_EPOCH => Err ( io:: const_error!(
1616- io:: ErrorKind :: InvalidInput ,
1617- "timestamp is too large to set as a file time" ,
1618- ) ) ,
1619- Some ( _) => Err ( io:: const_error!(
1620- io:: ErrorKind :: InvalidInput ,
1621- "timestamp is too small to set as a file time" ,
1622- ) ) ,
1623- None => Ok ( libc:: timespec { tv_sec : 0 , tv_nsec : libc:: UTIME_OMIT as _ } ) ,
1624- } ;
16251607 cfg_select ! {
16261608 any( target_os = "redox" , target_os = "espidf" , target_os = "horizon" , target_os = "nuttx" ) => {
16271609 // Redox doesn't appear to support `UTIME_OMIT`.
@@ -1634,36 +1616,18 @@ impl File {
16341616 ) )
16351617 }
16361618 target_vendor = "apple" => {
1637- let mut buf = [ mem:: MaybeUninit :: <libc:: timespec>:: uninit( ) ; 3 ] ;
1638- let mut num_times = 0 ;
1639- let mut attrlist: libc:: attrlist = unsafe { mem:: zeroed( ) } ;
1640- attrlist. bitmapcount = libc:: ATTR_BIT_MAP_COUNT ;
1641- if times. created. is_some( ) {
1642- buf[ num_times] . write( to_timespec( times. created) ?) ;
1643- num_times += 1 ;
1644- attrlist. commonattr |= libc:: ATTR_CMN_CRTIME ;
1645- }
1646- if times. modified. is_some( ) {
1647- buf[ num_times] . write( to_timespec( times. modified) ?) ;
1648- num_times += 1 ;
1649- attrlist. commonattr |= libc:: ATTR_CMN_MODTIME ;
1650- }
1651- if times. accessed. is_some( ) {
1652- buf[ num_times] . write( to_timespec( times. accessed) ?) ;
1653- num_times += 1 ;
1654- attrlist. commonattr |= libc:: ATTR_CMN_ACCTIME ;
1655- }
1619+ let ta = TimesAttrlist :: from_times( & times) ?;
16561620 cvt( unsafe { libc:: fsetattrlist(
16571621 self . as_raw_fd( ) ,
1658- ( & raw const attrlist ) . cast :: <libc :: c_void> ( ) . cast_mut ( ) ,
1659- buf . as_ptr ( ) . cast :: <libc :: c_void> ( ) . cast_mut ( ) ,
1660- num_times * size_of :: <libc :: timespec> ( ) ,
1622+ ta . attrlist ( ) ,
1623+ ta . times_buf ( ) ,
1624+ ta . times_buf_size ( ) ,
16611625 0
16621626 ) } ) ?;
16631627 Ok ( ( ) )
16641628 }
16651629 target_os = "android" => {
1666- let times = [ to_timespec ( times. accessed) ?, to_timespec ( times. modified) ?] ;
1630+ let times = [ file_time_to_timespec ( times. accessed) ?, file_time_to_timespec ( times. modified) ?] ;
16671631 // futimens requires Android API level 19
16681632 cvt( unsafe {
16691633 weak!(
@@ -1697,14 +1661,81 @@ impl File {
16971661 return Ok ( ( ) ) ;
16981662 }
16991663 }
1700- let times = [ to_timespec ( times. accessed) ?, to_timespec ( times. modified) ?] ;
1664+ let times = [ file_time_to_timespec ( times. accessed) ?, file_time_to_timespec ( times. modified) ?] ;
17011665 cvt( unsafe { libc:: futimens( self . as_raw_fd( ) , times. as_ptr( ) ) } ) ?;
17021666 Ok ( ( ) )
17031667 }
17041668 }
17051669 }
17061670}
17071671
1672+ #[ cfg( not( any(
1673+ target_os = "redox" ,
1674+ target_os = "espidf" ,
1675+ target_os = "horizon" ,
1676+ target_os = "nuttx" ,
1677+ ) ) ) ]
1678+ fn file_time_to_timespec ( time : Option < SystemTime > ) -> io:: Result < libc:: timespec > {
1679+ match time {
1680+ Some ( time) if let Some ( ts) = time. t . to_timespec ( ) => Ok ( ts) ,
1681+ Some ( time) if time > crate :: sys:: time:: UNIX_EPOCH => Err ( io:: const_error!(
1682+ io:: ErrorKind :: InvalidInput ,
1683+ "timestamp is too large to set as a file time" ,
1684+ ) ) ,
1685+ Some ( _) => Err ( io:: const_error!(
1686+ io:: ErrorKind :: InvalidInput ,
1687+ "timestamp is too small to set as a file time" ,
1688+ ) ) ,
1689+ None => Ok ( libc:: timespec { tv_sec : 0 , tv_nsec : libc:: UTIME_OMIT as _ } ) ,
1690+ }
1691+ }
1692+
1693+ #[ cfg( target_vendor = "apple" ) ]
1694+ struct TimesAttrlist {
1695+ buf : [ mem:: MaybeUninit < libc:: timespec > ; 3 ] ,
1696+ attrlist : libc:: attrlist ,
1697+ num_times : usize ,
1698+ }
1699+
1700+ #[ cfg( target_vendor = "apple" ) ]
1701+ impl TimesAttrlist {
1702+ fn from_times ( times : & FileTimes ) -> io:: Result < Self > {
1703+ let mut this = Self {
1704+ buf : [ mem:: MaybeUninit :: < libc:: timespec > :: uninit ( ) ; 3 ] ,
1705+ attrlist : unsafe { mem:: zeroed ( ) } ,
1706+ num_times : 0 ,
1707+ } ;
1708+ this. attrlist . bitmapcount = libc:: ATTR_BIT_MAP_COUNT ;
1709+ if times. created . is_some ( ) {
1710+ this. buf [ this. num_times ] . write ( file_time_to_timespec ( times. created ) ?) ;
1711+ this. num_times += 1 ;
1712+ attrlist. commonattr |= libc:: ATTR_CMN_CRTIME ;
1713+ }
1714+ if times. modified . is_some ( ) {
1715+ this. buf [ this. num_times ] . write ( file_time_to_timespec ( times. modified ) ?) ;
1716+ this. num_times += 1 ;
1717+ attrlist. commonattr |= libc:: ATTR_CMN_MODTIME ;
1718+ }
1719+ if times. accessed . is_some ( ) {
1720+ this. buf [ this. num_times ] . write ( file_time_to_timespec ( times. accessed ) ?) ;
1721+ this. num_times += 1 ;
1722+ attrlist. commonattr |= libc:: ATTR_CMN_ACCTIME ;
1723+ }
1724+ }
1725+
1726+ fn attrlist ( & self ) -> * mut libc:: c_void {
1727+ ( & raw const self . attrlist ) . cast :: < libc:: c_void > ( ) . cast_mut ( )
1728+ }
1729+
1730+ fn times_buf ( & self ) -> * mut libc:: c_void {
1731+ self . buf . as_ptr ( ) . cast :: < libc:: c_void > ( ) . cast_mut ( )
1732+ }
1733+
1734+ fn times_buf_size ( & self ) -> usize {
1735+ self . num_times * size_of :: < libc:: timespec > ( )
1736+ }
1737+ }
1738+
17081739impl DirBuilder {
17091740 pub fn new ( ) -> DirBuilder {
17101741 DirBuilder { mode : 0o777 }
0 commit comments