feat(libarchive): added FileWritter, also apparently formatted sys
parent
f9c5faeda8
commit
eb9f6a5cb1
|
@ -56,7 +56,7 @@ pub enum ReadFilter {
|
|||
Rpm,
|
||||
Uu,
|
||||
Xz,
|
||||
Zstd
|
||||
Zstd,
|
||||
}
|
||||
|
||||
impl ReadFilter {
|
||||
|
@ -69,7 +69,7 @@ impl ReadFilter {
|
|||
ReadFilter::Lzma => Some(".lzma"),
|
||||
ReadFilter::Xz => Some(".xz"),
|
||||
ReadFilter::Zstd => Some(".zstd"),
|
||||
_ => None
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
pub mod archive;
|
||||
pub mod error;
|
||||
pub mod read;
|
||||
mod write;
|
||||
|
||||
pub use archive::{
|
||||
Entry, ExtractOption, ExtractOptions, Handle, ReadCompression, ReadFilter, ReadFormat,
|
||||
|
|
|
@ -2,7 +2,6 @@ use crate::archive::Entry;
|
|||
use crate::error::ArchiveError;
|
||||
use crate::read::Archive;
|
||||
use libarchive3_sys::ffi;
|
||||
use libc::{c_void, ssize_t};
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::marker;
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
use super::file::FileWriter;
|
||||
use crate::error::ArchiveError;
|
||||
use crate::Handle;
|
||||
use crate::{WriteFilter, WriteFormat};
|
||||
use libarchive3_sys::ffi;
|
||||
use std::ffi::CString;
|
||||
use std::path::Path;
|
||||
|
||||
pub struct Builder {
|
||||
handle: *mut ffi::Struct_archive,
|
||||
consumed: bool,
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
pub fn new() -> Self {
|
||||
Builder::default()
|
||||
}
|
||||
|
||||
pub fn add_filter(&mut self, filter: WriteFilter) -> crate::Result<()> {
|
||||
let result = match filter {
|
||||
WriteFilter::B64Encode => unsafe {
|
||||
ffi::archive_write_add_filter_b64encode(self.handle)
|
||||
},
|
||||
WriteFilter::Bzip2 => unsafe { ffi::archive_write_add_filter_bzip2(self.handle) },
|
||||
WriteFilter::Compress => unsafe { ffi::archive_write_add_filter_compress(self.handle) },
|
||||
WriteFilter::Grzip => unsafe { ffi::archive_write_add_filter_grzip(self.handle) },
|
||||
WriteFilter::Gzip => unsafe { ffi::archive_write_add_filter_gzip(self.handle) },
|
||||
WriteFilter::Lrzip => unsafe { ffi::archive_write_add_filter_lrzip(self.handle) },
|
||||
WriteFilter::Lzip => unsafe { ffi::archive_write_add_filter_lzip(self.handle) },
|
||||
WriteFilter::Lzma => unsafe { ffi::archive_write_add_filter_lzma(self.handle) },
|
||||
WriteFilter::Lzop => unsafe { ffi::archive_write_add_filter_lzop(self.handle) },
|
||||
WriteFilter::None => unsafe { ffi::archive_write_add_filter_none(self.handle) },
|
||||
WriteFilter::Program(prog) => {
|
||||
let c_prog = CString::new(prog).unwrap();
|
||||
unsafe { ffi::archive_write_add_filter_program(self.handle, c_prog.as_ptr()) }
|
||||
}
|
||||
WriteFilter::UuEncode => unsafe { ffi::archive_write_add_filter_uuencode(self.handle) },
|
||||
WriteFilter::Xz => unsafe { ffi::archive_write_add_filter_xz(self.handle) },
|
||||
};
|
||||
match result {
|
||||
ffi::ARCHIVE_OK => Ok(()),
|
||||
_ => Result::from(self as &dyn Handle),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_format(&self, format: WriteFormat) -> crate::Result<()> {
|
||||
let result = match format {
|
||||
WriteFormat::SevenZip => unsafe { ffi::archive_write_set_format_7zip(self.handle) },
|
||||
WriteFormat::ArBsd => unsafe { ffi::archive_write_set_format_ar_bsd(self.handle) },
|
||||
WriteFormat::ArSvr4 => unsafe { ffi::archive_write_set_format_ar_svr4(self.handle) },
|
||||
WriteFormat::Cpio => unsafe { ffi::archive_write_set_format_cpio(self.handle) },
|
||||
WriteFormat::CpioNewc => unsafe {
|
||||
ffi::archive_write_set_format_cpio_newc(self.handle)
|
||||
},
|
||||
WriteFormat::Gnutar => unsafe { ffi::archive_write_set_format_gnutar(self.handle) },
|
||||
WriteFormat::Iso9660 => unsafe { ffi::archive_write_set_format_iso9660(self.handle) },
|
||||
WriteFormat::Mtree => unsafe { ffi::archive_write_set_format_mtree(self.handle) },
|
||||
WriteFormat::MtreeClassic => unsafe {
|
||||
ffi::archive_write_set_format_mtree_classic(self.handle)
|
||||
},
|
||||
WriteFormat::Pax => unsafe { ffi::archive_write_set_format_pax(self.handle) },
|
||||
WriteFormat::PaxRestricted => unsafe {
|
||||
ffi::archive_write_set_format_pax_restricted(self.handle)
|
||||
},
|
||||
WriteFormat::Shar => unsafe { ffi::archive_write_set_format_shar(self.handle) },
|
||||
WriteFormat::SharDump => unsafe {
|
||||
ffi::archive_write_set_format_shar_dump(self.handle)
|
||||
},
|
||||
WriteFormat::Ustar => unsafe { ffi::archive_write_set_format_ustar(self.handle) },
|
||||
WriteFormat::V7tar => unsafe { ffi::archive_write_set_format_v7tar(self.handle) },
|
||||
WriteFormat::Xar => unsafe { ffi::archive_write_set_format_xar(self.handle) },
|
||||
WriteFormat::Zip => unsafe { ffi::archive_write_set_format_zip(self.handle) },
|
||||
};
|
||||
match result {
|
||||
ffi::ARCHIVE_OK => Ok(()),
|
||||
_ => Result::from(self as &dyn Handle),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open_file<T: AsRef<Path>>(mut self, file: T) -> crate::Result<FileWriter> {
|
||||
if self.consumed {
|
||||
return Err(ArchiveError::Consumed);
|
||||
}
|
||||
let c_file = CString::new(file.as_ref().to_string_lossy().as_bytes()).unwrap();
|
||||
let res = unsafe { ffi::archive_write_open_filename(self.handle, c_file.as_ptr()) };
|
||||
match res {
|
||||
ffi::ARCHIVE_OK => {
|
||||
self.consumed = true;
|
||||
Ok(FileWriter::new(self.handle))
|
||||
}
|
||||
_ => Err(ArchiveError::from(&self as &dyn Handle)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Builder {
|
||||
fn default() -> Self {
|
||||
unsafe {
|
||||
let handle = ffi::archive_write_new();
|
||||
if handle.is_null() {
|
||||
panic!("Allocation error");
|
||||
}
|
||||
Builder {
|
||||
handle,
|
||||
consumed: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Handle for Builder {
|
||||
unsafe fn handle(&self) -> *const ffi::Struct_archive {
|
||||
self.handle as *const _
|
||||
}
|
||||
|
||||
unsafe fn handle_mut(&mut self) -> *mut ffi::Struct_archive {
|
||||
self.handle
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Builder {
|
||||
fn drop(&mut self) {
|
||||
if !self.consumed {
|
||||
unsafe {
|
||||
ffi::archive_write_free(self.handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
use super::WriteEntry;
|
||||
use crate::Entry;
|
||||
use crate::Handle;
|
||||
use libarchive3_sys::ffi;
|
||||
use libarchive3_sys::ffi::c_void;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
|
||||
pub struct FileWriter {
|
||||
handle: *mut ffi::Struct_archive,
|
||||
closed: bool,
|
||||
}
|
||||
|
||||
impl Handle for FileWriter {
|
||||
unsafe fn handle(&self) -> *const ffi::Struct_archive {
|
||||
self.handle as *const _
|
||||
}
|
||||
|
||||
unsafe fn handle_mut(&mut self) -> *mut ffi::Struct_archive {
|
||||
self.handle
|
||||
}
|
||||
}
|
||||
|
||||
impl FileWriter {
|
||||
pub fn new(handle: *mut ffi::Struct_archive) -> Self {
|
||||
FileWriter {
|
||||
handle,
|
||||
closed: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn append_path<P: AsRef<Path>>(
|
||||
&mut self,
|
||||
entry: &mut WriteEntry,
|
||||
path: P,
|
||||
) -> io::Result<()> {
|
||||
unsafe {
|
||||
ffi::archive_write_header(self.handle_mut(), entry.entry_mut());
|
||||
}
|
||||
|
||||
let mut f = fs::File::open(path)?;
|
||||
let mut buf = [0; 8192];
|
||||
|
||||
loop {
|
||||
match f.read(&mut buf) {
|
||||
Ok(0) => return Ok(()),
|
||||
Ok(written) => unsafe {
|
||||
ffi::archive_write_data(self.handle_mut(), buf.as_ptr() as *const _, written);
|
||||
},
|
||||
Err(err) => match err.kind() {
|
||||
io::ErrorKind::Interrupted => (),
|
||||
_ => return Err(err),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn close(&mut self) {
|
||||
unsafe {
|
||||
ffi::archive_write_close(self.handle_mut());
|
||||
}
|
||||
|
||||
self.closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for FileWriter {
|
||||
fn drop(&mut self) {
|
||||
if !self.closed {
|
||||
self.close();
|
||||
}
|
||||
|
||||
unsafe {
|
||||
ffi::archive_write_free(self.handle_mut());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
mod builder;
|
||||
mod file;
|
||||
|
||||
use crate::Entry;
|
||||
pub use builder::Builder;
|
||||
use libarchive3_sys::ffi;
|
||||
|
||||
pub struct WriteEntry {
|
||||
entry: *mut ffi::Struct_archive_entry,
|
||||
}
|
||||
|
||||
impl WriteEntry {
|
||||
pub fn new() -> Self {
|
||||
let entry = unsafe { ffi::archive_entry_new() };
|
||||
|
||||
Self { entry }
|
||||
}
|
||||
}
|
||||
|
||||
impl Entry for WriteEntry {
|
||||
unsafe fn entry(&self) -> *const ffi::Struct_archive_entry {
|
||||
self.entry as *const _
|
||||
}
|
||||
|
||||
unsafe fn entry_mut(&mut self) -> *mut ffi::Struct_archive_entry {
|
||||
self.entry
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for WriteEntry {
|
||||
fn drop(&mut self) {
|
||||
unsafe { ffi::archive_entry_free(self.entry_mut()) }
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,10 +1,10 @@
|
|||
mod repo;
|
||||
|
||||
use axum::extract::FromRef;
|
||||
use axum::Router;
|
||||
use repo::RepoGroupManager;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{RwLock, Arc};
|
||||
use axum::extract::FromRef;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Config {
|
||||
|
|
Loading…
Reference in New Issue