When trying to upload individual files with scp, I ran into some unknown error
s being reported. Looking at the source, it looks like this is the host sending a response packet which the library doesn't recognise, after sending the initial request to start an scp transfer.
I was transferring relatively large files and with spaces in filenames and directories so I did a few tests to narrow down the actual problem. Filesize isn't important, nor is local filename, but remote filename seems to have issues if there are spaces. I haven't managed to construct a very simple test case which produces unknown error
, but I have identified several which produce ambiguous target
which seem to be errors in the client:
for dest in vec![
"/tmp/foo.txt",
"/tmp/foo?.txt",
"/tmp/foo bar.txt",
"/tmp/foo bar/foo.txt",
"/tmp/foo bar/foo bar.txt",
"/tmp/foo\\ bar/foo\\ bar.txt"
] {
println!("DEST: {}", dest);
let scp = self.session.open_scp()?;
let res = scp.upload("/tmp/foo.txt", dest);
match res {
Ok(_) => println!("OK"),
Err(e) => println!("ERR: {}", e)
}
}
For this test setup I created "/tmp/foo bar"
on the remote host. I also tried this test with raw strings and by constructing paths with Path::new
first to rule out issues there, but it behaves the same in both cases.
Results were:
DEST: /tmp/foo.txt
OK
DEST: /tmp/foo?.txt
OK
DEST: /tmp/foo bar.txt
ERR: Scp error: scp: ambiguous target
DEST: /tmp/foo bar/foo.txt
ERR: Scp error: scp: ambiguous target
DEST: /tmp/foo bar/foo bar.txt
ERR: Scp error: scp: ambiguous target
DEST: /tmp/foo\ bar/foo\ bar.txt
OK
You can see I can fix the issue manually by escaping any spaces in the remote path, but especially given I'm actually trying to pass it a Path
I'd expect any necessary escaping to be handled by the library, as a Path
like /tmp/foo bar
correctly identifies the target.
I'm not very familiar with the low-level SSH / SCP protocol here but I'm assuming this library is failing to correctly quote it in the way the protocol desires and failing in these edge cases.
If you're open to PRs I might see if I can fix this issue myself and add my test cases above to the unit tests; I see you've tested recursive uploads, implicit target dir, etc. but not any edgecases around funny filenames. I ran into this while working on a little project to learn Rust so this seems like a straightforward issue for me to tackle while I'm here.
EDIT:
I identified how to get unknown error
, as well; it's if the destination path contains brackets:
DEST: /tmp/(foo)/foo.txt
ERR: Scp error: unknown error.
DEST: /tmp/(foo).txt
ERR: Scp error: unknown error.
DEST: /tmp/\(foo\).txt
OK
...and again, backslashing fixes them.