]>
Commit | Line | Data |
---|---|---|
f7d4e4b5 | 1 | use anyhow::{Error}; |
e9c9409a DM |
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) }; | |
f701d033 DM |
34 | let mut decoder = pxar::SequentialDecoder::new(&mut reader, pxar::flags::DEFAULT); |
35 | decoder.set_callback(move |path| { | |
5defa71b | 36 | if verbose { |
02c93163 | 37 | println!("{:?}", path); |
5defa71b | 38 | } |
e9c9409a | 39 | Ok(()) |
7dcbe051 CE |
40 | }); |
41 | ||
fa7e957c | 42 | if let Err(err) = decoder.restore(&base, &Vec::new()) { |
8968258b | 43 | eprintln!("pxar decode failed - {}", err); |
e9c9409a DM |
44 | } |
45 | }); | |
46 | ||
47 | let pipe = unsafe { std::fs::File::from_raw_fd(tx) }; | |
48 | ||
49 | Ok(Self { pipe: Some(pipe), child: Some(child) }) | |
50 | } | |
51 | } | |
52 | ||
5defa71b | 53 | impl Write for PxarDecodeWriter { |
e9c9409a DM |
54 | |
55 | fn write(&mut self, buffer: &[u8]) -> Result<usize, std::io::Error> { | |
56 | let pipe = match self.pipe { | |
57 | Some(ref mut pipe) => pipe, | |
58 | None => unreachable!(), | |
59 | }; | |
60 | pipe.write(buffer) | |
61 | } | |
62 | ||
63 | fn flush(&mut self) -> Result<(), std::io::Error> { | |
64 | let pipe = match self.pipe { | |
65 | Some(ref mut pipe) => pipe, | |
66 | None => unreachable!(), | |
67 | }; | |
68 | pipe.flush() | |
69 | } | |
70 | } |