@@ -12,8 +12,23 @@ use crate::sys::time::SystemTime;
1212use crate :: sys:: { cvt, cvt_r} ;
1313use crate :: sys_common:: { AsInner , FromInner } ;
1414
15+ #[ cfg( any(
16+ all( target_os = "linux" , target_env = "gnu" ) ,
17+ target_os = "macos" ,
18+ target_os = "ios" ,
19+ ) ) ]
20+ use crate :: sys:: weak:: syscall;
21+ #[ cfg( target_os = "macos" ) ]
22+ use crate :: sys:: weak:: weak;
23+
1524use libc:: { c_int, mode_t} ;
1625
26+ #[ cfg( any(
27+ target_os = "macos" ,
28+ target_os = "ios" ,
29+ all( target_os = "linux" , target_env = "gnu" )
30+ ) ) ]
31+ use libc:: c_char;
1732#[ cfg( any( target_os = "linux" , target_os = "emscripten" , target_os = "android" ) ) ]
1833use libc:: dirfd;
1934#[ cfg( any( target_os = "linux" , target_os = "emscripten" ) ) ]
@@ -92,7 +107,7 @@ cfg_has_statx! {{
92107 // Default `stat64` contains no creation time.
93108 unsafe fn try_statx(
94109 fd: c_int,
95- path: * const libc :: c_char,
110+ path: * const c_char,
96111 flags: i32 ,
97112 mask: u32 ,
98113 ) -> Option <io:: Result <FileAttr >> {
@@ -107,7 +122,7 @@ cfg_has_statx! {{
107122 syscall! {
108123 fn statx(
109124 fd: c_int,
110- pathname: * const libc :: c_char,
125+ pathname: * const c_char,
111126 flags: c_int,
112127 mask: libc:: c_uint,
113128 statxbuf: * mut libc:: statx
@@ -756,7 +771,7 @@ impl File {
756771 cfg_has_statx ! {
757772 if let Some ( ret) = unsafe { try_statx(
758773 fd,
759- b"\0 " as * const _ as * const libc :: c_char,
774+ b"\0 " as * const _ as * const c_char,
760775 libc:: AT_EMPTY_PATH | libc:: AT_STATX_SYNC_AS_STAT ,
761776 libc:: STATX_ALL ,
762777 ) } {
@@ -1087,15 +1102,28 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> {
10871102 let link = cstr ( link) ?;
10881103 cfg_if:: cfg_if! {
10891104 if #[ cfg( any( target_os = "vxworks" , target_os = "redox" , target_os = "android" ) ) ] {
1090- // VxWorks, Redox, and old versions of Android lack `linkat`, so use
1091- // `link` instead. POSIX leaves it implementation-defined whether
1092- // `link` follows symlinks, so rely on the `symlink_hard_link` test
1093- // in library/std/src/fs/tests.rs to check the behavior.
1105+ // VxWorks and Redox lack `linkat`, so use `link` instead. POSIX leaves
1106+ // it implementation-defined whether `link` follows symlinks, so rely on the
1107+ // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior.
1108+ // Android has `linkat` on newer versions, but we happen to know `link`
1109+ // always has the correct behavior, so it's here as well.
10941110 cvt( unsafe { libc:: link( original. as_ptr( ) , link. as_ptr( ) ) } ) ?;
1111+ } else if #[ cfg( target_os = "macos" ) ] {
1112+ // On MacOS, older versions (<=10.9) lack support for linkat while newer
1113+ // versions have it. We want to use linkat if it is available, so we use weak!
1114+ // to check. `linkat` is preferable to `link` ecause it gives us a flag to
1115+ // specify how symlinks should be handled. We pass 0 as the flags argument,
1116+ // meaning it shouldn't follow symlinks.
1117+ weak!( fn linkat( c_int, * const c_char, c_int, * const c_char, c_int) -> c_int) ;
1118+
1119+ if let Some ( f) = linkat. get( ) {
1120+ cvt( unsafe { f( libc:: AT_FDCWD , original. as_ptr( ) , libc:: AT_FDCWD , link. as_ptr( ) , 0 ) } ) ?;
1121+ } else {
1122+ cvt( unsafe { libc:: link( original. as_ptr( ) , link. as_ptr( ) ) } ) ?;
1123+ } ;
10951124 } else {
1096- // Use `linkat` with `AT_FDCWD` instead of `link` as `linkat` gives
1097- // us a flag to specify how symlinks should be handled. Pass 0 as
1098- // the flags argument, meaning don't follow symlinks.
1125+ // Where we can, use `linkat` instead of `link`; see the comment above
1126+ // this one for details on why.
10991127 cvt( unsafe { libc:: linkat( libc:: AT_FDCWD , original. as_ptr( ) , libc:: AT_FDCWD , link. as_ptr( ) , 0 ) } ) ?;
11001128 }
11011129 }
@@ -1278,7 +1306,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
12781306 fn fclonefileat(
12791307 srcfd: libc:: c_int,
12801308 dst_dirfd: libc:: c_int,
1281- dst: * const libc :: c_char,
1309+ dst: * const c_char,
12821310 flags: libc:: c_int
12831311 ) -> libc:: c_int
12841312 }
0 commit comments