diff options
| author | Aris Merchant <wizkarim@gmail.com> | 2021-06-02 22:53:03 -0700 |
|---|---|---|
| committer | inquisitivecrystal <22333129+inquisitivecrystal@users.noreply.github.com> | 2021-07-09 23:24:36 -0700 |
| commit | dc38d87505f4b1e381f143b4f34704df6a24e57e (patch) | |
| tree | 942ea729fd03e8bc7cbeb2e3ea6d884a13e37230 /library/std/src | |
| parent | 8eae2eb1d31da4b0bbdb80dcf2625535c3f147ae (diff) | |
| download | rust-dc38d87505f4b1e381f143b4f34704df6a24e57e.tar.gz rust-dc38d87505f4b1e381f143b4f34704df6a24e57e.zip | |
Fix linker error
This makes `fs::hard_link` use weak! for some platforms, thereby preventing a linker error.
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/sys/unix/fs.rs | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index bec0d5898ac..4bbf334fc13 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -14,6 +14,12 @@ use crate::sys_common::{AsInner, FromInner}; use libc::{c_int, mode_t}; +#[cfg(any( + target_os = "macos", + target_os = "ios", + all(target_os = "linux", target_env = "gnu") +))] +use libc::c_char; #[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))] use libc::dirfd; #[cfg(any(target_os = "linux", target_os = "emscripten"))] @@ -92,7 +98,7 @@ cfg_has_statx! {{ // Default `stat64` contains no creation time. unsafe fn try_statx( fd: c_int, - path: *const libc::c_char, + path: *const c_char, flags: i32, mask: u32, ) -> Option<io::Result<FileAttr>> { @@ -107,7 +113,7 @@ cfg_has_statx! {{ syscall! { fn statx( fd: c_int, - pathname: *const libc::c_char, + pathname: *const c_char, flags: c_int, mask: libc::c_uint, statxbuf: *mut libc::statx @@ -756,7 +762,7 @@ impl File { cfg_has_statx! { if let Some(ret) = unsafe { try_statx( fd, - b"\0" as *const _ as *const libc::c_char, + b"\0" as *const _ as *const c_char, libc::AT_EMPTY_PATH | libc::AT_STATX_SYNC_AS_STAT, libc::STATX_ALL, ) } { @@ -1087,15 +1093,28 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> { let link = cstr(link)?; cfg_if::cfg_if! { if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android"))] { - // VxWorks, Redox, and old versions of Android lack `linkat`, so use - // `link` instead. POSIX leaves it implementation-defined whether - // `link` follows symlinks, so rely on the `symlink_hard_link` test - // in library/std/src/fs/tests.rs to check the behavior. + // VxWorks and Redox lack `linkat`, so use `link` instead. POSIX leaves + // it implementation-defined whether `link` follows symlinks, so rely on the + // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior. + // Android has `linkat` on newer versions, but we happen to know `link` + // always has the correct behavior, so it's here as well. cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?; + } else if #[cfg(target_os = "macos")] { + // On MacOS, older versions (<=10.9) lack support for linkat while newer + // versions have it. We want to use linkat if it is available, so we use weak! + // to check. `linkat` is preferable to `link` ecause it gives us a flag to + // specify how symlinks should be handled. We pass 0 as the flags argument, + // meaning it shouldn't follow symlinks. + weak!(fn linkat(c_int, *const c_char, c_int, *const c_char, c_int) -> c_int); + + if let Some(f) = linkat.get() { + cvt(unsafe { f(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?; + } else { + cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?; + }; } else { - // Use `linkat` with `AT_FDCWD` instead of `link` as `linkat` gives - // us a flag to specify how symlinks should be handled. Pass 0 as - // the flags argument, meaning don't follow symlinks. + // Where we can, use `linkat` instead of `link`; see the comment above + // this one for details on why. cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?; } } @@ -1278,7 +1297,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> { fn fclonefileat( srcfd: libc::c_int, dst_dirfd: libc::c_int, - dst: *const libc::c_char, + dst: *const c_char, flags: libc::c_int ) -> libc::c_int } |
