Treat empty remote dest path as home directory

scp's "host:" (no path after the colon) means the remote home
directory, reusing the source's basename. resolve_dest_paths only
recognized a directory target via a trailing '/', so an empty path
fell through and was used literally as the filename, producing an
empty --dest-final and hanging the remote --server --recv.
This commit is contained in:
2026-08-25 17:13:58 -04:00
parent 3fd6ba3bd0
commit 9326890987
+13 -2
View File
@@ -81,10 +81,11 @@ pub fn resolve_dest_paths(
effective_compress: bool,
partial_ext: &str,
) -> DestPaths {
// DEST may name a directory (trailing '/') -- in that case reuse the
// DEST may name a directory (trailing '/', or empty as in scp's
// "host:" meaning the remote home directory) -- in that case reuse the
// source's logical basename underneath it. Otherwise DEST names the file
// directly.
let dest_logical = if dest_path.ends_with('/') {
let dest_logical = if dest_path.is_empty() || dest_path.ends_with('/') {
let base = Path::new(&source_stripped.logical)
.file_name()
.map(|n| n.to_string_lossy().to_string())
@@ -240,6 +241,16 @@ mod tests {
assert_eq!(d.final_path, "/out/cap.pcap");
}
#[test]
fn dest_paths_empty_target_is_home_dir() {
// scp-style "host:" (empty remote path) means the remote home
// directory -- reuse the source's basename, don't leave it empty.
let src = strip_name("cap.pcap.partial", "partial");
let d = resolve_dest_paths("", &src, false, "partial");
assert_eq!(d.final_path, "cap.pcap");
assert_eq!(d.temp_path, "cap.pcap.partial");
}
#[test]
fn size_parsing() {
assert_eq!(parse_size("256k").unwrap(), 256 * 1024);