summaryrefslogtreecommitdiffstats
path: root/src/decompressor.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/decompressor.rs')
-rw-r--r--src/decompressor.rs190
1 files changed, 0 insertions, 190 deletions
diff --git a/src/decompressor.rs b/src/decompressor.rs
deleted file mode 100644
index d25c2f56..00000000
--- a/src/decompressor.rs
+++ /dev/null
@@ -1,190 +0,0 @@
-use std::collections::HashMap;
-use std::ffi::OsStr;
-use std::fmt;
-use std::io::{self, Read};
-use std::path::Path;
-use std::process::{self, Stdio};
-
-use globset::{Glob, GlobSet, GlobSetBuilder};
-
-/// A decompression command, contains the command to be spawned as well as any
-/// necessary CLI args.
-#[derive(Clone, Copy, Debug)]
-struct DecompressionCommand {
- cmd: &'static str,
- args: &'static [&'static str],
-}
-
-impl DecompressionCommand {
- /// Create a new decompress command
- fn new(
- cmd: &'static str,
- args: &'static [&'static str],
- ) -> DecompressionCommand {
- DecompressionCommand {
- cmd, args
- }
- }
-}
-
-impl fmt::Display for DecompressionCommand {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "{} {}", self.cmd, self.args.join(" "))
- }
-}
-
-lazy_static! {
- static ref DECOMPRESSION_COMMANDS: HashMap<
- &'static str,
- DecompressionCommand,
- > = {
- let mut m = HashMap::new();
-
- const ARGS: &[&str] = &["-d", "-c"];
- m.insert("gz", DecompressionCommand::new("gzip", ARGS));
- m.insert("bz2", DecompressionCommand::new("bzip2", ARGS));
- m.insert("xz", DecompressionCommand::new("xz", ARGS));
- m.insert("lz4", DecompressionCommand::new("lz4", ARGS));
-
- const LZMA_ARGS: &[&str] = &["--format=lzma", "-d", "-c"];
- m.insert("lzma", DecompressionCommand::new("xz", LZMA_ARGS));
-
- m
- };
- static ref SUPPORTED_COMPRESSION_FORMATS: GlobSet = {
- let mut builder = GlobSetBuilder::new();
- builder.add(Glob::new("*.gz").unwrap());
- builder.add(Glob::new("*.bz2").unwrap());
- builder.add(Glob::new("*.xz").unwrap());
- builder.add(Glob::new("*.lz4").unwrap());
- builder.add(Glob::new("*.lzma").unwrap());
- builder.build().unwrap()
- };
- static ref TAR_ARCHIVE_FORMATS: GlobSet = {
- let mut builder = GlobSetBuilder::new();
- builder.add(Glob::new("*.tar.gz").unwrap());
- builder.add(Glob::new("*.tar.xz").unwrap());
- builder.add(Glob::new("*.tar.bz2").unwrap());
- builder.add(Glob::new("*.tar.lz4").unwrap());
- builder.add(Glob::new("*.tgz").unwrap());
- builder.add(Glob::new("*.txz").unwrap());
- builder.add(Glob::new("*.tbz2").unwrap());
- builder.build().unwrap()
- };
-}
-
-/// DecompressionReader provides an `io::Read` implementation for a limited
-/// set of compression formats.
-#[derive(Debug)]
-pub struct DecompressionReader {
- cmd: DecompressionCommand,
- child: process::Child,
- done: bool,
-}
-
-impl DecompressionReader {
- /// Returns a handle to the stdout of the spawned decompression process for
- /// `path`, which can be directly searched in the worker. When the returned
- /// value is exhausted, the underlying process is reaped. If the underlying
- /// process fails, then its stderr is read and converted into a normal
- /// io::Error.
- ///
- /// If there is any error in spawning the decompression command, then
- /// return `None`, after outputting any necessary debug or error messages.
- pub fn from_path(path: &Path) -> Option<DecompressionReader> {
- let extension = match path.extension().and_then(OsStr::to_str) {
- Some(extension) => extension,
- None => {
- debug!(
- "{}: failed to get compresson extension", path.display());
- return None;
- }
- };
- let decompression_cmd = match DECOMPRESSION_COMMANDS.get(extension) {
- Some(cmd) => cmd,
- None => {
- debug!(
- "{}: failed to get decompression command", path.display());
- return None;
- }
- };
- let cmd = process::Command::new(decompression_cmd.cmd)
- .args(decompression_cmd.args)
- .arg(path)
- .stdout(Stdio::piped())
- .stderr(Stdio::piped())
- .spawn();
- let child = match cmd {
- Ok(process) => process,
- Err(_) => {
- debug!(
- "{}: decompression command '{}' not found",
- path.display(), decompression_cmd.cmd);
- return None;
- }
- };
- Some(DecompressionReader::new(*decompression_cmd, child))
- }
-
- fn new(
- cmd: DecompressionCommand,
- child: process::Child,
- ) -> DecompressionReader {
- DecompressionReader {
- cmd: cmd,
- child: child,
- done: false,
- }
- }
-
- fn read_error(&mut self) -> io::Result<io::Error> {
- let mut errbytes = vec![];
- self.child.stderr.as_mut().unwrap().read_to_end(&mut errbytes)?;
- let errstr = String::from_utf8_lossy(&errbytes);
- let errstr = errstr.trim();
-
- Ok(if errstr.is_empty() {
- let msg = format!("decompression command failed: '{}'", self.cmd);
- io::Error::new(io::ErrorKind::Other, msg)
- } else {
- let msg = format!(
- "decompression command '{}' failed: {}", self.cmd, errstr);
- io::Error::new(io::ErrorKind::Other, msg)
- })
- }
-}
-
-impl io::Read for DecompressionReader {
- fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
- if self.done {
- return Ok(0);
- }
- let nread = self.child.stdout.as_mut().unwrap().read(buf)?;
- if nread == 0 {
- self.done = true;
- // Reap the child now that we're done reading.
- // If the command failed, report stderr as an error.
- if !self.child.wait()?.success() {
- return Err(self.read_error()?);
- }
- }
- Ok(nread)
- }
-}
-
-/// Returns true if the given path contains a supported compression format or
-/// is a TAR archive.
-pub fn is_compressed(path: &Path) -> bool {
- is_supported_compression_format(path) || is_tar_archive(path)
-}
-
-/// Returns true if the given path matches any one of the supported compression
-/// formats
-fn is_supported_compression_format(path: &Path) -> bool {
- SUPPORTED_COMPRESSION_FORMATS.is_match(path)
-}
-
-/// Returns true if the given path matches any of the known TAR file formats.
-fn is_tar_archive(path: &Path) -> bool {
- TAR_ARCHIVE_FORMATS.is_match(path)
-}