#[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);
}
}
}