1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#[macro_use]
extern crate lazy_static;
extern crate libc;
extern crate tar_sys as raw;
use std::io::{Error, ErrorKind, Result};
use std::path::Path;
use std::sync::Mutex;
lazy_static! {
static ref MUTEX: Mutex<isize> = Mutex::new(0);
}
macro_rules! done(
($result:expr) => (
if $result != 0 {
return Err(Error::last_os_error());
}
);
);
macro_rules! raise(
($message:expr) => (
return Err(Error::new(ErrorKind::Other, $message))
);
);
macro_rules! path_to_cstr(
($path:expr) => (match $path.to_str() {
Some(path) => match CString::new(path) {
Ok(path) => path,
_ => raise!("the path is invalid"),
},
_ => raise!("the path is invalid"),
});
);
pub struct Archive {
raw: *mut raw::TAR,
}
impl Archive {
pub fn open<T: AsRef<Path>>(path: T) -> Result<Archive> {
use libc::O_RDONLY;
use std::ffi::CString;
let mut tar = 0 as *mut raw::TAR;
unsafe {
let _guard = MUTEX.lock().unwrap();
let path = path_to_cstr!(path.as_ref());
done!(raw::tar_open(&mut tar, path.as_ptr(), 0 as *mut _, O_RDONLY, 0, 0));
}
Ok(Archive { raw: tar })
}
pub fn extract<T: AsRef<Path>>(&self, path: T) -> Result<()> {
use std::ffi::CString;
unsafe {
let _guard = MUTEX.lock().unwrap();
let path = path_to_cstr!(path.as_ref());
done!(raw::tar_extract_all(self.raw, path.as_ptr()));
}
Ok(())
}
}
#[inline]
pub fn open<T: AsRef<Path>>(path: T) -> Result<Archive> {
Archive::open(path)
}
impl Drop for Archive {
#[inline]
fn drop(&mut self) {
unsafe {
let _guard = MUTEX.lock().unwrap();
raw::tar_close(self.raw);
}
}
}