diff --git a/src/uu/touch/src/touch.rs b/src/uu/touch/src/touch.rs index bcb0beaca..e8c4fcd2f 100644 --- a/src/uu/touch/src/touch.rs +++ b/src/uu/touch/src/touch.rs @@ -103,7 +103,11 @@ Try 'touch --help' for more information."##, let path = pathbuf.as_path(); - if !path.exists() { + if let Err(e) = path.metadata() { + if e.kind() != std::io::ErrorKind::NotFound { + return Err(e.map_err_context(|| format!("setting times of {}", filename.quote()))); + } + if matches.contains_id(options::NO_CREATE) { continue; } diff --git a/tests/by-util/test_touch.rs b/tests/by-util/test_touch.rs index 346e27919..7a70b556e 100644 --- a/tests/by-util/test_touch.rs +++ b/tests/by-util/test_touch.rs @@ -701,3 +701,49 @@ fn test_touch_leap_second() { assert_eq!(atime.unix_seconds() - epoch.unix_seconds(), 60); assert_eq!(mtime.unix_seconds() - epoch.unix_seconds(), 60); } + +#[test] +#[cfg(not(windows))] +// File::create doesn't support trailing separator in Windows +fn test_touch_trailing_slash_no_create() { + let (at, mut ucmd) = at_and_ucmd!(); + at.touch("file"); + ucmd.args(&["-c", "file/"]).fails().code_is(1); + + let (at, mut ucmd) = at_and_ucmd!(); + ucmd.args(&["-c", "no-file/"]).succeeds(); + assert!( + !at.file_exists("no-file") && !at.dir_exists("no-file") && !at.symlink_exists("no-file") + ); + + let (at, mut ucmd) = at_and_ucmd!(); + at.relative_symlink_file("nowhere", "dangling"); + ucmd.args(&["-c", "dangling/"]).succeeds(); + assert!(!at.file_exists("nowhere")); + assert!(at.symlink_exists("dangling")); + + let (at, mut ucmd) = at_and_ucmd!(); + at.relative_symlink_file("loop", "loop"); + ucmd.args(&["-c", "loop/"]).fails().code_is(1); + assert!(!at.file_exists("loop")); + + #[cfg(not(target_os = "macos"))] + // MacOS supports trailing slash for symlinks to files + { + let (at, mut ucmd) = at_and_ucmd!(); + at.touch("file2"); + at.relative_symlink_file("file2", "link1"); + ucmd.args(&["-c", "link1/"]).fails().code_is(1); + assert!(at.file_exists("file2")); + assert!(at.symlink_exists("link1")); + } + + let (at, mut ucmd) = at_and_ucmd!(); + at.mkdir("dir"); + ucmd.args(&["-c", "dir/"]).succeeds(); + + let (at, mut ucmd) = at_and_ucmd!(); + at.mkdir("dir2"); + at.relative_symlink_dir("dir2", "link2"); + ucmd.args(&["-c", "link2/"]).succeeds(); +}