scpcap v0
This commit is contained in:
+108
@@ -0,0 +1,108 @@
|
||||
use clap::Parser;
|
||||
|
||||
/// scp-like tool for copying (possibly still-growing) pcap capture files.
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(name = "scpcap")]
|
||||
pub struct ClientCli {
|
||||
/// Source: local path or [user@]host:path. If the name ends in the
|
||||
/// partial extension, it's treated as still growing.
|
||||
pub source: String,
|
||||
|
||||
/// Destination: local path or [user@]host:path.
|
||||
pub dest: String,
|
||||
|
||||
/// Compress in flight; destination is written as a streaming .pcap.zst.
|
||||
/// Only "zstd" is supported.
|
||||
#[arg(long, value_name = "CODEC", num_args = 0..=1, default_missing_value = "zstd", require_equals = true)]
|
||||
pub compress: Option<String>,
|
||||
|
||||
/// Target chunk size for compression, e.g. "256k", "1m".
|
||||
#[arg(long, default_value = "256k")]
|
||||
pub chunk: String,
|
||||
|
||||
/// zstd compression level (lower = faster; default tuned for throughput
|
||||
/// to stay competitive with `scp -C`).
|
||||
#[arg(long, default_value_t = crate::zstd_frame::DEFAULT_LEVEL)]
|
||||
pub level: i32,
|
||||
|
||||
/// Suffix identifying a still-growing file.
|
||||
#[arg(long, default_value = "partial")]
|
||||
pub extension: String,
|
||||
}
|
||||
|
||||
/// Remote helper mode, ssh-spawned by the client (like `rsync --server`).
|
||||
/// Not meant to be invoked directly by a user.
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(name = "scpcap --server")]
|
||||
pub struct ServerCli {
|
||||
#[command(flatten)]
|
||||
pub role: ServerRoleFlags,
|
||||
|
||||
/// Source path to read (--send mode).
|
||||
#[arg(long)]
|
||||
pub source: Option<String>,
|
||||
|
||||
/// Source's final (non-partial) path, for rename detection (--send mode).
|
||||
#[arg(long)]
|
||||
pub final_source: Option<String>,
|
||||
|
||||
/// Whether the source is a still-growing (partial) file (--send mode).
|
||||
#[arg(long)]
|
||||
pub partial: bool,
|
||||
|
||||
/// Compress in flight (--send mode). No adjacent positional args in
|
||||
/// --server mode, so (unlike ClientCli's --compress) there's no
|
||||
/// ambiguity requiring `--compress=zstd` -- `--compress zstd` is fine.
|
||||
#[arg(long, value_name = "CODEC", num_args = 0..=1, default_missing_value = "zstd")]
|
||||
pub compress: Option<String>,
|
||||
|
||||
/// Target chunk size for compression (--send mode).
|
||||
#[arg(long, default_value = "256k")]
|
||||
pub chunk: String,
|
||||
|
||||
/// zstd compression level (--send mode).
|
||||
#[arg(long, default_value_t = crate::zstd_frame::DEFAULT_LEVEL)]
|
||||
pub level: i32,
|
||||
|
||||
/// Destination final path (--recv mode).
|
||||
#[arg(long)]
|
||||
pub dest_final: Option<String>,
|
||||
|
||||
/// Destination temp path, written while in flight (--recv mode).
|
||||
#[arg(long)]
|
||||
pub dest_temp: Option<String>,
|
||||
}
|
||||
|
||||
/// The clap-facing shape of the role choice: two mutually exclusive,
|
||||
/// individually-long-named flags, matching rsync's `--server --send`/
|
||||
/// `--server --recv` convention. Clap's derive has no direct way to map two
|
||||
/// separate boolean flags onto one enum field, so this stays a flag pair at
|
||||
/// the parsing boundary and converts to `ServerRole` via `role()` below.
|
||||
#[derive(clap::Args, Debug)]
|
||||
#[group(required = true, multiple = false)]
|
||||
pub struct ServerRoleFlags {
|
||||
#[arg(long)]
|
||||
pub send: bool,
|
||||
#[arg(long)]
|
||||
pub recv: bool,
|
||||
}
|
||||
|
||||
/// The role a `--server` process plays, for the rest of the code to match on
|
||||
/// instead of checking two booleans.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ServerRole {
|
||||
Send,
|
||||
Recv,
|
||||
}
|
||||
|
||||
impl ServerCli {
|
||||
/// The `--group(required, exclusive)` on `ServerRoleFlags` guarantees
|
||||
/// exactly one of `send`/`recv` is set by the time parsing succeeds.
|
||||
pub fn role(&self) -> ServerRole {
|
||||
if self.role.send {
|
||||
ServerRole::Send
|
||||
} else {
|
||||
ServerRole::Recv
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user