From 27d891111f5fe68181b726bd374527a825ddc160 Mon Sep 17 00:00:00 2001 From: ddidderr Date: Sun, 21 Dec 2025 13:41:49 +0100 Subject: [PATCH] fix(client): don't create local file if remote file doesn't exist MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, the get command would create/truncate the local file before starting the download, then delete it on error. This could inadvertently destroy an existing local file if the remote file didn't exist. Now the download completes to memory first, and the local file is only written after a successful transfer. This is safe for TFTP since files are typically small (bootloaders, configs, etc.). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- crates/pfs-tftp/src/bin/tftp.rs | 34 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/crates/pfs-tftp/src/bin/tftp.rs b/crates/pfs-tftp/src/bin/tftp.rs index 955add2..1f0f082 100644 --- a/crates/pfs-tftp/src/bin/tftp.rs +++ b/crates/pfs-tftp/src/bin/tftp.rs @@ -248,30 +248,28 @@ fn main() -> ExitCode { } }; - // Create output file - let mut file = match File::create(&local_file) { - Ok(f) => f, + // Download to memory first - only create local file on success + let data = match client.get(&remote_file, args.mode) { + Ok(data) => data, Err(e) => { - eprintln!("Error creating file '{local_file}': {e}"); + eprintln!("Error: {e}"); return ExitCode::FAILURE; } }; - // Download - match client.get_to_writer(&remote_file, args.mode, &mut file) { - Ok(bytes) => { - if args.verbose { - eprintln!("Received {bytes} bytes"); - } - println!("Downloaded '{remote_file}' -> '{local_file}' ({bytes} bytes)"); - } - Err(e) => { - // Clean up partial file - let _ = std::fs::remove_file(&local_file); - eprintln!("Error: {e}"); - return ExitCode::FAILURE; - } + // Write to local file + if let Err(e) = std::fs::write(&local_file, &data) { + eprintln!("Error writing file '{local_file}': {e}"); + return ExitCode::FAILURE; } + + if args.verbose { + eprintln!("Received {} bytes", data.len()); + } + println!( + "Downloaded '{remote_file}' -> '{local_file}' ({} bytes)", + data.len() + ); } Command::Put {