(initial) Align formatting and code style to project standards. Add live_test.sh: full automated integration suite against a real SSH server Show [name] for optional positionals, allow filtering import by name too Fix transfer rough edges: value-name hint, identity warnings, single-profile export Add transfer subcommand for bulk profile export/import Harden forced ssh flags: accept-new host keys, block multiplexing, tighten identity auth release build opts Standardize error messages, formatting, and code style. Refine --help text for consistency. Update comments for clarity and tone alignment. Normalize user-facing --help text for tone/format consistency Show real mapping grammar in --help, make --via repeatable, trim comments Match vmic's custom top-level --help renderer Implement porthole v0.1: profiles, supervised open/close, reconnect Fix --via/-J grammar and --force process-group kill added .gitignore
26 lines
804 B
Rust
26 lines
804 B
Rust
//! Atomic file writes: write to a sibling temp file, then `rename` over the
|
|
//! target. Matters here specifically for the instance JSON file, which the
|
|
//! supervisor rewrites on every state change while it may be alive for
|
|
//! months; a reader (`status`/`list`) must never observe a half-written
|
|
//! file, and a crash mid-write must never corrupt the last-known-good state.
|
|
|
|
use std::io::Write;
|
|
use std::path::Path;
|
|
|
|
pub fn write(path: &Path, contents: &[u8]) -> std::io::Result<()>
|
|
{
|
|
let tmp = path.with_extension(format!(
|
|
"{}.tmp.{}",
|
|
path.extension().and_then(|e| e.to_str()).unwrap_or(""),
|
|
std::process::id()
|
|
));
|
|
|
|
{
|
|
let mut f = std::fs::File::create(&tmp)?;
|
|
f.write_all(contents)?;
|
|
f.sync_all()?;
|
|
}
|
|
|
|
std::fs::rename(&tmp, path)
|
|
}
|