use crate::entry::EntryMut;
use crate::error::{Error, Result};
use std::ops::{BitOr, BitOrAssign};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ExtractFlags(i32);
impl ExtractFlags {
pub const NONE: ExtractFlags = ExtractFlags(0);
pub const OWNER: ExtractFlags = ExtractFlags(0x0001);
pub const PERM: ExtractFlags = ExtractFlags(0x0002);
pub const TIME: ExtractFlags = ExtractFlags(0x0004);
pub const NO_OVERWRITE: ExtractFlags = ExtractFlags(0x0008);
pub const UNLINK: ExtractFlags = ExtractFlags(0x0010);
pub const ACL: ExtractFlags = ExtractFlags(0x0020);
pub const FFLAGS: ExtractFlags = ExtractFlags(0x0040);
pub const XATTR: ExtractFlags = ExtractFlags(0x0080);
pub const SECURE_SYMLINKS: ExtractFlags = ExtractFlags(0x0100);
pub const SECURE_NODOTDOT: ExtractFlags = ExtractFlags(0x0200);
pub const NO_AUTODIR: ExtractFlags = ExtractFlags(0x0400);
pub const NO_OVERWRITE_NEWER: ExtractFlags = ExtractFlags(0x0800);
pub const SPARSE: ExtractFlags = ExtractFlags(0x1000);
pub const MAC_METADATA: ExtractFlags = ExtractFlags(0x2000);
pub const NO_HFS_COMPRESSION: ExtractFlags = ExtractFlags(0x4000);
pub const HFS_COMPRESSION_FORCED: ExtractFlags = ExtractFlags(0x8000);
pub const SECURE_NOABSOLUTEPATHS: ExtractFlags = ExtractFlags(0x10000);
pub const CLEAR_NOCHANGE_FFLAGS: ExtractFlags = ExtractFlags(0x20000);
pub const SAFE_WRITES: ExtractFlags = ExtractFlags(0x40000);
pub fn bits(&self) -> i32 {
self.0
}
}
impl BitOr for ExtractFlags {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
ExtractFlags(self.0 | rhs.0)
}
}
impl BitOrAssign for ExtractFlags {
fn bitor_assign(&mut self, rhs: Self) {
self.0 |= rhs.0;
}
}
pub struct WriteDisk {
archive: *mut libarchive2_sys::archive,
}
unsafe impl Send for WriteDisk {}
impl WriteDisk {
pub fn new() -> Result<Self> {
unsafe {
let archive = libarchive2_sys::archive_write_disk_new();
if archive.is_null() {
return Err(Error::NullPointer);
}
Ok(WriteDisk { archive })
}
}
pub fn set_options(&mut self, flags: ExtractFlags) -> Result<()> {
unsafe {
Error::from_return_code(
libarchive2_sys::archive_write_disk_set_options(self.archive, flags.bits()),
self.archive,
)?;
}
Ok(())
}
pub fn set_standard_lookup(&mut self) -> Result<()> {
unsafe {
Error::from_return_code(
libarchive2_sys::archive_write_disk_set_standard_lookup(self.archive),
self.archive,
)?;
}
Ok(())
}
pub fn write_header(&mut self, entry: &EntryMut) -> Result<()> {
let _guard = crate::locale::WindowsUTF8LocaleGuard::new();
unsafe {
Error::from_return_code(
libarchive2_sys::archive_write_header(self.archive, entry.entry),
self.archive,
)?;
}
Ok(())
}
pub fn write_data(&mut self, data: &[u8]) -> Result<usize> {
unsafe {
let ret = libarchive2_sys::archive_write_data(
self.archive,
data.as_ptr() as *const std::os::raw::c_void,
data.len(),
);
if ret < 0 {
Err(Error::from_archive(self.archive))
} else {
Ok(ret as usize)
}
}
}
pub fn finish_entry(&mut self) -> Result<()> {
unsafe {
Error::from_return_code(
libarchive2_sys::archive_write_finish_entry(self.archive),
self.archive,
)?;
}
Ok(())
}
pub fn close(mut self) -> Result<()> {
unsafe {
if !self.archive.is_null() {
Error::from_return_code(
libarchive2_sys::archive_write_close(self.archive),
self.archive,
)?;
libarchive2_sys::archive_write_free(self.archive);
self.archive = std::ptr::null_mut();
}
}
Ok(())
}
}
impl Drop for WriteDisk {
fn drop(&mut self) {
unsafe {
if !self.archive.is_null() {
libarchive2_sys::archive_write_close(self.archive);
libarchive2_sys::archive_write_free(self.archive);
}
}
}
}