use failure::*; use std::thread; use std::os::unix::io::FromRawFd; use std::path::{Path, PathBuf}; use std::io::Write; use crate::pxar::decoder::*; /// Writer implementation to deccode a .pxar archive (download). pub struct PxarBackupWriter { pipe: Option, child: Option>, } impl Drop for PxarBackupWriter { fn drop(&mut self) { drop(self.pipe.take()); self.child.take().unwrap().join().unwrap(); } } impl PxarBackupWriter { pub fn new(base: &Path, _verbose: bool) -> Result { let (rx, tx) = nix::unistd::pipe()?; let base = PathBuf::from(base); let child = thread::spawn(move|| { let mut reader = unsafe { std::fs::File::from_raw_fd(rx) }; let mut decoder = PxarDecoder::new(&mut reader); if let Err(err) = decoder.restore(&base, & |path| { println!("RESTORE: {:?}", path); Ok(()) }) { eprintln!("pxar decode failed - {}", err); } }); let pipe = unsafe { std::fs::File::from_raw_fd(tx) }; Ok(Self { pipe: Some(pipe), child: Some(child) }) } } impl Write for PxarBackupWriter { fn write(&mut self, buffer: &[u8]) -> Result { let pipe = match self.pipe { Some(ref mut pipe) => pipe, None => unreachable!(), }; pipe.write(buffer) } fn flush(&mut self) -> Result<(), std::io::Error> { let pipe = match self.pipe { Some(ref mut pipe) => pipe, None => unreachable!(), }; pipe.flush() } }