]>
Commit | Line | Data |
---|---|---|
e9c9409a DM |
1 | use failure::*; |
2 | ||
3 | use std::thread; | |
4 | use std::os::unix::io::FromRawFd; | |
5 | use std::path::{Path, PathBuf}; | |
6 | use std::io::Write; | |
e9c9409a | 7 | |
3dbfe5b1 | 8 | use crate::pxar; |
e9c9409a | 9 | |
8968258b | 10 | /// Writer implementation to deccode a .pxar archive (download). |
e9c9409a | 11 | |
5defa71b | 12 | pub struct PxarDecodeWriter { |
e9c9409a DM |
13 | pipe: Option<std::fs::File>, |
14 | child: Option<thread::JoinHandle<()>>, | |
15 | } | |
16 | ||
5defa71b | 17 | impl Drop for PxarDecodeWriter { |
e9c9409a DM |
18 | |
19 | fn drop(&mut self) { | |
20 | drop(self.pipe.take()); | |
21 | self.child.take().unwrap().join().unwrap(); | |
22 | } | |
23 | } | |
24 | ||
5defa71b | 25 | impl PxarDecodeWriter { |
e9c9409a | 26 | |
5defa71b | 27 | pub fn new(base: &Path, verbose: bool) -> Result<Self, Error> { |
e9c9409a DM |
28 | let (rx, tx) = nix::unistd::pipe()?; |
29 | ||
d5c34d98 | 30 | let base = PathBuf::from(base); |
e9c9409a DM |
31 | |
32 | let child = thread::spawn(move|| { | |
33 | let mut reader = unsafe { std::fs::File::from_raw_fd(rx) }; | |
3dbfe5b1 | 34 | let mut decoder = pxar::SequentialDecoder::new(&mut reader); |
5defa71b | 35 | |
d5c34d98 | 36 | if let Err(err) = decoder.restore(&base, & |path| { |
5defa71b | 37 | if verbose { |
02c93163 | 38 | println!("{:?}", path); |
5defa71b | 39 | } |
e9c9409a DM |
40 | Ok(()) |
41 | }) { | |
8968258b | 42 | eprintln!("pxar decode failed - {}", err); |
e9c9409a DM |
43 | } |
44 | }); | |
45 | ||
46 | let pipe = unsafe { std::fs::File::from_raw_fd(tx) }; | |
47 | ||
48 | Ok(Self { pipe: Some(pipe), child: Some(child) }) | |
49 | } | |
50 | } | |
51 | ||
5defa71b | 52 | impl Write for PxarDecodeWriter { |
e9c9409a DM |
53 | |
54 | fn write(&mut self, buffer: &[u8]) -> Result<usize, std::io::Error> { | |
55 | let pipe = match self.pipe { | |
56 | Some(ref mut pipe) => pipe, | |
57 | None => unreachable!(), | |
58 | }; | |
59 | pipe.write(buffer) | |
60 | } | |
61 | ||
62 | fn flush(&mut self) -> Result<(), std::io::Error> { | |
63 | let pipe = match self.pipe { | |
64 | Some(ref mut pipe) => pipe, | |
65 | None => unreachable!(), | |
66 | }; | |
67 | pipe.flush() | |
68 | } | |
69 | } |