use clap::Parser;
use gunzip_split::{escape_cc, list_contents, uncompress_all, unconcatenate_files, Progress};
use std::fs::File;
use std::io::{ErrorKind, Read, Seek};
use std::path::PathBuf;
#[derive(Parser)]
#[clap(version, about, long_about = None)]
struct Opt {
#[clap(short, long)]
force: bool,
#[clap(short, long, group = "input")]
_decompress: bool,
#[clap(short, long, group = "input")]
split_only: bool,
#[clap(short, long, group = "input")]
list_only: bool,
#[clap(short, long, parse(from_os_str), name = "DIRECTORY", required_unless_present("list-only"))]
output_directory: Option<PathBuf>,
#[clap(name = "FILE", parse(from_os_str))]
path: PathBuf,
}
fn process(opt: Opt) -> std::io::Result<()> {
let input = opt.path;
let outdir = opt.output_directory;
let overwrite = opt.force;
let mut gzfile = File::open(&input)?;
if opt.list_only {
list_contents(&mut gzfile, |p| {
if let Progress::FileBegin { name, .. } = p {
println!("{}", escape_cc(name))
}
})?;
} else if opt.split_only {
let files = list_contents(&mut gzfile, |_| {})?;
unconcatenate_files(&mut gzfile, &files, &outdir.unwrap(), overwrite, |p| match p {
Progress::FileBegin { name, .. } => eprint!("{}: ", escape_cc(name)),
Progress::FileDone { .. } => eprintln!("OK."),
Progress::FileFailed { error } => {
if error.kind() == ErrorKind::AlreadyExists {
eprintln!("ERROR: {} (use -f to overwrite).", error);
} else {
eprintln!("ERROR: {}.", error);
}
}
Progress::ProgressStep => {}
})?;
} else {
uncompress_all(&mut gzfile, &outdir.unwrap(), overwrite, |p| match p {
Progress::FileBegin { name, .. } => eprint!("{}: ", escape_cc(name)),
Progress::FileDone { .. } => eprintln!("OK."),
_ => {}
})?;
}
let mut buf = [0u8; 1];
if let (Ok(pos), Ok(i)) = (gzfile.stream_position(), gzfile.read(&mut buf)) {
if i > 0 {
eprintln!(
"WARNING: {} contains non-gzip data starting at byte {}.",
input.display(),
pos
);
}
}
Ok(())
}
fn main() {
let opt = Opt::parse();
let result = process(opt);
if let Err(e) = result {
if e.kind() == ErrorKind::AlreadyExists {
eprintln!("ERROR: {} (use -f to overwrite).", e);
} else {
eprintln!("ERROR: {}.", e);
}
eprintln!("Aborted.");
std::process::exit(1);
}
}