mod client_impl;
pub mod config;
use anyhow::Result;
use clap::Subcommand;
use std::path::PathBuf;
pub use client_impl::Client;
#[derive(Subcommand)]
pub enum TftpcAction {
Get {
server: String,
remote_file: String,
#[arg(value_name = "LOCAL_FILE")]
local_file: Option<PathBuf>,
#[arg(short, long, default_value = "69")]
port: u16,
#[arg(short, long, default_value = "512")]
block_size: u16,
#[arg(short, long, default_value = "5")]
timeout: u64,
},
Put {
server: String,
local_file: PathBuf,
#[arg(value_name = "REMOTE_FILE")]
remote_file: Option<String>,
#[arg(short, long, default_value = "69")]
port: u16,
#[arg(short, long, default_value = "512")]
block_size: u16,
#[arg(short, long, default_value = "5")]
timeout: u64,
},
}
pub fn run_with_config(
action: TftpcAction,
config: Option<&config::TftpcConfigFile>,
) -> Result<()> {
match action {
TftpcAction::Get {
server,
remote_file,
local_file,
port,
block_size,
timeout,
} => {
let client_config = config.and_then(|c| c.get.clone()).unwrap_or_default();
let cfg = client_config.merge_cli(server.clone(), port, block_size, timeout);
let local_path = local_file.unwrap_or_else(|| PathBuf::from(&remote_file));
let server_display = cfg.server.as_deref().unwrap_or("unknown");
let port_display = cfg.port.unwrap_or(69);
log::info!(
"Downloading {} from {}:{}",
remote_file,
server_display,
port_display
);
log::info!("Saving to: {}", local_path.display());
let client = Client::new(cfg)?;
client.get(&remote_file, &local_path)?;
log::info!("Download completed successfully");
}
TftpcAction::Put {
server,
local_file,
remote_file,
port,
block_size,
timeout,
} => {
let client_config = config.and_then(|c| c.put.clone()).unwrap_or_default();
let cfg = client_config.merge_cli(server.clone(), port, block_size, timeout);
if !local_file.exists() {
log::error!("Local file does not exist: {}", local_file.display());
return Err(anyhow::anyhow!("Local file does not exist"));
}
let remote_name = remote_file.unwrap_or_else(|| {
local_file
.file_name()
.and_then(|n| n.to_str())
.unwrap_or("file")
.to_string()
});
let server_display = cfg.server.as_deref().unwrap_or("unknown");
let port_display = cfg.port.unwrap_or(69);
log::info!(
"Uploading {} to {}:{}",
local_file.display(),
server_display,
port_display
);
log::info!("Remote file: {}", remote_name);
let client = Client::new(cfg)?;
client.put(&local_file, &remote_name)?;
log::info!("Upload completed successfully");
}
}
Ok(())
}