From 0cbbf30f65f83f05f9f484634afe40b1784b859a Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 16 Oct 2020 07:13:17 -0700 Subject: [PATCH 1/5] Add another test for hardlinks to symlinks. --- tests/fs_additional.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fs_additional.rs b/tests/fs_additional.rs index 2df13c82..a0abf2ba 100644 --- a/tests/fs_additional.rs +++ b/tests/fs_additional.rs @@ -416,4 +416,5 @@ fn symlink_hard_link() { let _ = check!(tmpdir.open("hard_link")); check!(tmpdir.rename("file", &tmpdir, "file.renamed")); assert!(tmpdir.open("hard_link").is_err()); + assert_eq!(check!(tmpdir.read_link("hard_link")), Path::new("file")); } From c25853084ccb31a257e34c10da20e46ce44ae1dc Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 16 Oct 2020 07:16:38 -0700 Subject: [PATCH 2/5] More asserts. --- tests/fs_additional.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/fs_additional.rs b/tests/fs_additional.rs index a0abf2ba..d13b5c4a 100644 --- a/tests/fs_additional.rs +++ b/tests/fs_additional.rs @@ -413,8 +413,17 @@ fn symlink_hard_link() { check!(tmpdir.create("file")); check!(symlink_file("file", &tmpdir, "symlink")); check!(tmpdir.hard_link("symlink", &tmpdir, "hard_link")); + let _ = check!(tmpdir.open("file")); + assert!(tmpdir.open("file.renamed").is_err()); + let _ = check!(tmpdir.open("symlink")); let _ = check!(tmpdir.open("hard_link")); check!(tmpdir.rename("file", &tmpdir, "file.renamed")); + assert!(tmpdir.open("file").is_err()); + let _ = check!(tmpdir.open("file.renamed")); + assert!(tmpdir.open("symlink").is_err()); assert!(tmpdir.open("hard_link").is_err()); + assert!(tmpdir.read_link("file").is_err()); + assert!(tmpdir.read_link("file.renamed").is_err()); + assert_eq!(check!(tmpdir.read_link("symlink")), Path::new("file")); assert_eq!(check!(tmpdir.read_link("hard_link")), Path::new("file")); } From ddf7200c1221ab65419721c1b5d5f670990e541b Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 16 Oct 2020 07:34:29 -0700 Subject: [PATCH 3/5] More asserts. --- tests/fs_additional.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/fs_additional.rs b/tests/fs_additional.rs index d13b5c4a..3586ab27 100644 --- a/tests/fs_additional.rs +++ b/tests/fs_additional.rs @@ -413,6 +413,9 @@ fn symlink_hard_link() { check!(tmpdir.create("file")); check!(symlink_file("file", &tmpdir, "symlink")); check!(tmpdir.hard_link("symlink", &tmpdir, "hard_link")); + assert!(check!(tmpdir.symlink_metadata("hard_link")) + .file_type() + .is_symlink()); let _ = check!(tmpdir.open("file")); assert!(tmpdir.open("file.renamed").is_err()); let _ = check!(tmpdir.open("symlink")); @@ -426,4 +429,12 @@ fn symlink_hard_link() { assert!(tmpdir.read_link("file.renamed").is_err()); assert_eq!(check!(tmpdir.read_link("symlink")), Path::new("file")); assert_eq!(check!(tmpdir.read_link("hard_link")), Path::new("file")); + check!(tmpdir.remove_file("file.renamed")); + assert!(tmpdir.open("file").is_err()); + assert!(tmpdir.open("file.renamed").is_err()); + assert!(tmpdir.open("symlink").is_err()); + assert!(tmpdir.open("hard_link").is_err()); + assert!(check!(tmpdir.symlink_metadata("hard_link")) + .file_type() + .is_symlink()); } From fa06aaed233980e6ddd517b1f08a338fcb198639 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 16 Oct 2020 07:50:45 -0700 Subject: [PATCH 4/5] Add an ambient form of the test. --- tests/fs_additional.rs | 60 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/tests/fs_additional.rs b/tests/fs_additional.rs index 3586ab27..025f39ab 100644 --- a/tests/fs_additional.rs +++ b/tests/fs_additional.rs @@ -403,6 +403,66 @@ fn dir_searchable_unreadable() { .is_err()); } +/// This test is the same as `symlink_hard_link` but uses `std::fs`' +/// ambient API instead of `cap_std`. The purpose of this test is to +/// confirm fundamentally OS-specific behaviors. +#[test] +fn symlink_hard_link_ambient() { + #[cfg(unix)] + use std::os::unix::fs::symlink; + #[cfg(windows)] + use std::os::windows::fs::symlink_file; + + let dir = tempfile::tempdir().unwrap(); + + check!(std::fs::File::create(dir.path().join("file"))); + #[cfg(not(windows))] + check!(symlink("file", dir.path().join("symlink"))); + #[cfg(windows)] + check!(symlink_file("file", dir.path().join("symlink"))); + check!(std::fs::hard_link( + dir.path().join("symlink"), + dir.path().join("hard_link") + )); + assert!( + check!(std::fs::symlink_metadata(dir.path().join("hard_link"))) + .file_type() + .is_symlink() + ); + let _ = check!(std::fs::File::open(dir.path().join("file"))); + assert!(std::fs::File::open(dir.path().join("file.renamed")).is_err()); + let _ = check!(std::fs::File::open(dir.path().join("symlink"))); + let _ = check!(std::fs::File::open(dir.path().join("hard_link"))); + check!(std::fs::rename( + dir.path().join("file"), + dir.path().join("file.renamed") + )); + assert!(std::fs::File::open(dir.path().join("file")).is_err()); + let _ = check!(std::fs::File::open(dir.path().join("file.renamed"))); + assert!(std::fs::File::open(dir.path().join("symlink")).is_err()); + assert!(std::fs::File::open(dir.path().join("hard_link")).is_err()); + assert!(std::fs::read_link(dir.path().join("file")).is_err()); + assert!(std::fs::read_link(dir.path().join("file.renamed")).is_err()); + assert_eq!( + check!(std::fs::read_link(dir.path().join("symlink"))), + Path::new("file") + ); + assert_eq!( + check!(std::fs::read_link(dir.path().join("hard_link"))), + Path::new("file") + ); + check!(std::fs::remove_file(dir.path().join("file.renamed"))); + assert!(std::fs::File::open(dir.path().join("file")).is_err()); + assert!(std::fs::File::open(dir.path().join("file.renamed")).is_err()); + assert!(std::fs::File::open(dir.path().join("symlink")).is_err()); + assert!(std::fs::File::open(dir.path().join("hard_link")).is_err()); + assert!( + check!(std::fs::symlink_metadata(dir.path().join("hard_link"))) + .file_type() + .is_symlink() + ); +} + /// POSIX says that whether or not `link` follows symlinks in the `old` /// path is implementation-defined. We want `hard_link` to not follow /// symbolic links. From 6cbb6a614aee1e845575c8f03b3eedb7b7530e0f Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 16 Oct 2020 12:41:22 -0700 Subject: [PATCH 5/5] Disable the ambient version of symlink_hard_link on macOS and FreeBSD. --- tests/fs_additional.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fs_additional.rs b/tests/fs_additional.rs index 025f39ab..ddc982fa 100644 --- a/tests/fs_additional.rs +++ b/tests/fs_additional.rs @@ -407,6 +407,7 @@ fn dir_searchable_unreadable() { /// ambient API instead of `cap_std`. The purpose of this test is to /// confirm fundamentally OS-specific behaviors. #[test] +#[cfg_attr(any(target_os = "macos", target_os = "freebsd"), ignore)] // submitted to upstream as https://github.com/rust-lang/rust/pull/78026 fn symlink_hard_link_ambient() { #[cfg(unix)] use std::os::unix::fs::symlink;