diff options
| author | Dan Gohman <dev@sunfishcode.online> | 2020-10-16 09:09:20 -0700 |
|---|---|---|
| committer | Dan Gohman <dev@sunfishcode.online> | 2020-10-16 12:05:49 -0700 |
| commit | 91a9f83dd1d73cfd451f81306361df3fafad84a5 (patch) | |
| tree | b3eff22b5672b6fbd8099552216dbc58c65ee78f /library/std/src/sys | |
| parent | a78a62fc996ba16f7a111c99520b23f77029f4eb (diff) | |
| download | rust-91a9f83dd1d73cfd451f81306361df3fafad84a5.tar.gz rust-91a9f83dd1d73cfd451f81306361df3fafad84a5.zip | |
Define `fs::hard_link` to not follow symlinks.
POSIX leaves it implementation-defined whether `link` follows symlinks. In practice, for example, on Linux it does not and on FreeBSD it does. So, switch to `linkat`, so that we can pick a behavior rather than depending on OS defaults. Pick the option to not follow symlinks. This is somewhat arbitrary, but seems the less surprising choice because hard linking is a very low-level feature which requires the source and destination to be on the same mounted filesystem, and following a symbolic link could end up in a different mounted filesystem.
Diffstat (limited to 'library/std/src/sys')
| -rw-r--r-- | library/std/src/sys/unix/fs.rs | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 819e8ef1841..88693e4786c 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1067,7 +1067,10 @@ pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { pub fn link(src: &Path, dst: &Path) -> io::Result<()> { let src = cstr(src)?; let dst = cstr(dst)?; - cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })?; + // Use `linkat` with `AT_FDCWD` instead of `link` as `link` leaves it + // implmentation-defined whether it follows symlinks. Pass 0 as the + // `linkat` flags argument so that we don't follow symlinks. + cvt(unsafe { libc::linkat(libc::AT_FDCWD, src.as_ptr(), libc::AT_FDCWD, dst.as_ptr(), 0) })?; Ok(()) } |
