@@ -827,7 +827,10 @@ pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
827827    Ok ( PathBuf :: from ( OsString :: from_vec ( buf) ) ) 
828828} 
829829
830- #[ cfg( not( any( target_os = "linux" ,  target_os = "android" ) ) ) ]  
830+ #[ cfg( not( any( target_os = "linux" ,  
831+               target_os = "android" ,  
832+               target_os = "macos" ,  
833+               target_os = "ios" ) ) ) ]  
831834pub  fn  copy ( from :  & Path ,  to :  & Path )  -> io:: Result < u64 >  { 
832835    use  crate :: fs:: File ; 
833836    if  !from. is_file ( )  { 
@@ -937,3 +940,85 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
937940    writer. set_permissions ( perm) ?; 
938941    Ok ( written) 
939942} 
943+ 
944+ #[ cfg( any( target_os = "macos" ,  target_os = "ios" ) ) ]  
945+ pub  fn  copy ( from :  & Path ,  to :  & Path )  -> io:: Result < u64 >  { 
946+     const  COPYFILE_ACL :  u32  = 1  << 0 ; 
947+     const  COPYFILE_STAT :  u32  = 1  << 1 ; 
948+     const  COPYFILE_XATTR :  u32  = 1  << 2 ; 
949+     const  COPYFILE_DATA :  u32  = 1  << 3 ; 
950+ 
951+     const  COPYFILE_SECURITY :  u32  = COPYFILE_STAT  | COPYFILE_ACL ; 
952+     const  COPYFILE_METADATA :  u32  = COPYFILE_SECURITY  | COPYFILE_XATTR ; 
953+     const  COPYFILE_ALL :  u32  = COPYFILE_METADATA  | COPYFILE_DATA ; 
954+ 
955+     const  COPYFILE_STATE_COPIED :  u32  = 8 ; 
956+ 
957+     #[ allow( non_camel_case_types) ]  
958+     type  copyfile_state_t  = * mut  libc:: c_void ; 
959+     #[ allow( non_camel_case_types) ]  
960+     type  copyfile_flags_t  = u32 ; 
961+ 
962+     extern  "C"  { 
963+         fn  copyfile ( 
964+             from :  * const  libc:: c_char , 
965+             to :  * const  libc:: c_char , 
966+             state :  copyfile_state_t , 
967+             flags :  copyfile_flags_t , 
968+         )  -> libc:: c_int ; 
969+         fn  copyfile_state_alloc ( )  -> copyfile_state_t ; 
970+         fn  copyfile_state_free ( state :  copyfile_state_t )  -> libc:: c_int ; 
971+         fn  copyfile_state_get ( 
972+             state :  copyfile_state_t , 
973+             flag :  u32 , 
974+             dst :  * mut  libc:: c_void , 
975+         )  -> libc:: c_int ; 
976+     } 
977+ 
978+     struct  FreeOnDrop ( copyfile_state_t ) ; 
979+     impl  Drop  for  FreeOnDrop  { 
980+         fn  drop ( & mut  self )  { 
981+             // The code below ensures that `FreeOnDrop` is never a null pointer 
982+             unsafe  { 
983+                 // `copyfile_state_free` returns -1 if the `to` or `from` files 
984+                 // cannot be closed. However, this is not considerd this an 
985+                 // error. 
986+                 copyfile_state_free ( self . 0 ) ; 
987+             } 
988+         } 
989+     } 
990+ 
991+     if  !from. is_file ( )  { 
992+         return  Err ( Error :: new ( ErrorKind :: InvalidInput , 
993+                               "the source path is not an existing regular file" ) ) 
994+     } 
995+ 
996+     // We ensure that `FreeOnDrop` never contains a null pointer so it is 
997+     // always safe to call `copyfile_state_free` 
998+     let  state = unsafe  { 
999+         let  state = copyfile_state_alloc ( ) ; 
1000+         if  state. is_null ( )  { 
1001+             return  Err ( crate :: io:: Error :: last_os_error ( ) ) ; 
1002+         } 
1003+         FreeOnDrop ( state) 
1004+     } ; 
1005+ 
1006+     cvt ( unsafe  { 
1007+         copyfile ( 
1008+             cstr ( from) ?. as_ptr ( ) , 
1009+             cstr ( to) ?. as_ptr ( ) , 
1010+             state. 0 , 
1011+             COPYFILE_ALL , 
1012+         ) 
1013+     } ) ?; 
1014+ 
1015+     let  mut  bytes_copied:  libc:: off_t  = 0 ; 
1016+     cvt ( unsafe  { 
1017+         copyfile_state_get ( 
1018+             state. 0 , 
1019+             COPYFILE_STATE_COPIED , 
1020+             & mut  bytes_copied as  * mut  libc:: off_t  as  * mut  libc:: c_void , 
1021+         ) 
1022+     } ) ?; 
1023+     Ok ( bytes_copied as  u64 ) 
1024+ } 
0 commit comments