install, mkdir: Handle dir/./ like dir/.

The dir/. special case was handled correctly, but dir/./ was not,
breaking gcc builds, which run:

../../../../src/libstdc++-v3/../install-sh -c -d debug/./

Bug-Ubuntu: https://bugs.launchpad.net/bugs/2117466
This commit is contained in:
Julian Andres Klode 2025-07-22 09:40:36 +02:00
parent a1a2734527
commit abb5300068
3 changed files with 27 additions and 3 deletions

View file

@ -534,12 +534,12 @@ pub fn display_permissions_unix(mode: mode_t, display_file_type: bool) -> String
result
}
/// For some programs like install or mkdir, dir/. can be provided
/// For some programs like install or mkdir, dir/. or dir/./ can be provided
/// Special case to match GNU's behavior:
/// install -d foo/. should work and just create foo/
/// install -d foo/. (and foo/./) should work and just create foo/
/// std::fs::create_dir("foo/."); fails in pure Rust
pub fn dir_strip_dot_for_creation(path: &Path) -> PathBuf {
if path.to_string_lossy().ends_with("/.") {
if path.to_string_lossy().ends_with("/.") || path.to_string_lossy().ends_with("/./") {
// Do a simple dance to strip the "/."
Path::new(&path).components().collect::<PathBuf>()
} else {

View file

@ -1518,6 +1518,13 @@ fn test_install_dir_dot() {
.arg("-v")
.succeeds()
.stdout_contains("creating directory 'dir5/cali'");
scene
.ucmd()
.arg("-d")
.arg("dir6/./")
.arg("-v")
.succeeds()
.stdout_contains("creating directory 'dir6'");
let at = &scene.fixtures;
@ -1526,6 +1533,7 @@ fn test_install_dir_dot() {
assert!(at.dir_exists("dir3"));
assert!(at.dir_exists("dir4/cal"));
assert!(at.dir_exists("dir5/cali"));
assert!(at.dir_exists("dir6"));
}
#[test]

View file

@ -332,6 +332,22 @@ fn test_mkdir_trailing_dot() {
println!("ls dest {}", result.stdout_str());
}
#[test]
fn test_mkdir_trailing_dot_and_slash() {
new_ucmd!().arg("-p").arg("-v").arg("test_dir").succeeds();
new_ucmd!()
.arg("-p")
.arg("-v")
.arg("test_dir_a/./")
.succeeds()
.stdout_contains("created directory 'test_dir_a'");
let scene = TestScenario::new("ls");
let result = scene.ucmd().arg("-al").run();
println!("ls dest {}", result.stdout_str());
}
#[test]
#[cfg(not(windows))]
fn test_umask_compliance() {