feat: process libarchive entries using Read API
parent
5743f4a3a5
commit
2e118d0283
|
@ -1,6 +1,7 @@
|
||||||
use crate::archive;
|
use crate::archive;
|
||||||
use std::error;
|
use std::error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, ArchiveError>;
|
pub type Result<T> = std::result::Result<T, ArchiveError>;
|
||||||
|
|
||||||
|
@ -48,3 +49,9 @@ impl<'a> From<&'a dyn archive::Handle> for Result<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ArchiveError> for io::Error {
|
||||||
|
fn from(err: ArchiveError) -> Self {
|
||||||
|
io::Error::new(io::ErrorKind::Other, format!("{}", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,18 +3,3 @@ pub mod error;
|
||||||
pub mod read;
|
pub mod read;
|
||||||
|
|
||||||
pub use error::Result;
|
pub use error::Result;
|
||||||
|
|
||||||
pub fn add(left: usize, right: usize) -> usize {
|
|
||||||
left + right
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn it_works() {
|
|
||||||
let result = add(2, 2);
|
|
||||||
assert_eq!(result, 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
|
use super::file::ArchiveFile;
|
||||||
use crate::archive::{Handle, ReadCompression, ReadFilter, ReadFormat};
|
use crate::archive::{Handle, ReadCompression, ReadFilter, ReadFormat};
|
||||||
use libarchive3_sys::ffi;
|
|
||||||
use crate::error::{ArchiveError, Result};
|
use crate::error::{ArchiveError, Result};
|
||||||
|
use crate::read::Archive;
|
||||||
|
use libarchive3_sys::ffi;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use super::file::ArchiveFile;
|
|
||||||
use crate::read::Archive;
|
|
||||||
|
|
||||||
/// A struct that allows configuration of the reader before it is created.
|
/// A struct that allows configuration of the reader before it is created.
|
||||||
pub struct Builder {
|
pub struct Builder {
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
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;
|
||||||
|
|
||||||
|
pub struct ReadEntry<'a, T: Archive> {
|
||||||
|
archive: *mut ffi::Struct_archive,
|
||||||
|
entry: *mut ffi::Struct_archive_entry,
|
||||||
|
offset: usize,
|
||||||
|
_ignored: marker::PhantomData<&'a T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
//impl<'b, T: Archive + 'b> ReadEntry<'b, T> {
|
||||||
|
// /// Create a new ReaderEntry from a raw pointer to an `archive_entry` struct
|
||||||
|
// ///
|
||||||
|
// /// # Safety
|
||||||
|
// /// The pointer must own the struct it points to, otherwise it may be freed twice
|
||||||
|
// pub unsafe fn new(archive: &'b mut T, handle: *mut ffi::Struct_archive_entry) -> Self {
|
||||||
|
// Self { archive, handle }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
impl<'a, T: Archive> Entry for ReadEntry<'a, T> {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Entries<'a, T: 'a + Archive> {
|
||||||
|
archive: &'a mut T, // entry: &'b mut ReadEntry<'b, T>
|
||||||
|
// entry_handle: *mut ffi::Struct_archive_entry, // entry: ReadEntry<'a, T>
|
||||||
|
}
|
||||||
|
|
||||||
|
// impl Default for ReadEntry {
|
||||||
|
// fn default() -> Self {
|
||||||
|
// Self {
|
||||||
|
// handle: std::ptr::null_mut(),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
impl<'a, T: 'a + Archive> Entries<'a, T> {
|
||||||
|
pub fn new(archive: &'a mut T) -> Self {
|
||||||
|
Self { archive }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// impl<'a, T: 'a + Archive> EntryFields<'a, T> {
|
||||||
|
// fn read_next_header(&'a mut self) -> crate::Result<Option<ReadEntry<'a, T>>> {
|
||||||
|
// let mut entry_ptr: *mut ffi::Struct_archive_entry = std::ptr::null_mut();
|
||||||
|
|
||||||
|
// let res = unsafe {
|
||||||
|
// ffi::archive_read_next_header(self.archive.handle() as *mut _, &mut entry_ptr)
|
||||||
|
// };
|
||||||
|
|
||||||
|
// match res {
|
||||||
|
// ffi::ARCHIVE_OK | ffi::ARCHIVE_WARN => Ok(Some(unsafe {
|
||||||
|
// EntryFields::new(self.archive, entry_ptr).into_entry()
|
||||||
|
// })),
|
||||||
|
// ffi::ARCHIVE_EOF => Ok(None),
|
||||||
|
// _ => Err(ArchiveError::Sys(
|
||||||
|
// self.archive.err_code(),
|
||||||
|
// self.archive.err_msg().to_owned(),
|
||||||
|
// )),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
impl<'a, T: Archive + 'a> Iterator for Entries<'a, T> {
|
||||||
|
type Item = crate::Result<ReadEntry<'a, T>>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let mut entry_ptr: *mut ffi::Struct_archive_entry = std::ptr::null_mut();
|
||||||
|
|
||||||
|
let res = unsafe {
|
||||||
|
ffi::archive_read_next_header(self.archive.handle() as *mut _, &mut entry_ptr)
|
||||||
|
};
|
||||||
|
|
||||||
|
match res {
|
||||||
|
ffi::ARCHIVE_OK | ffi::ARCHIVE_WARN => {
|
||||||
|
let entry = ReadEntry {
|
||||||
|
archive: unsafe { self.archive.handle_mut() },
|
||||||
|
entry: entry_ptr,
|
||||||
|
offset: 0,
|
||||||
|
_ignored: marker::PhantomData,
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(Ok(entry))
|
||||||
|
}
|
||||||
|
ffi::ARCHIVE_EOF => None,
|
||||||
|
_ => Some(Err(ArchiveError::Sys(
|
||||||
|
self.archive.err_code(),
|
||||||
|
self.archive.err_msg().to_owned(),
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: Archive> Read for ReadEntry<'a, T> {
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
let res =
|
||||||
|
unsafe { ffi::archive_read_data(self.archive, buf as *mut [u8] as *mut _, buf.len()) };
|
||||||
|
|
||||||
|
if res >= 0 {
|
||||||
|
let count: usize = res
|
||||||
|
.try_into()
|
||||||
|
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
||||||
|
self.offset += count;
|
||||||
|
|
||||||
|
Ok(count)
|
||||||
|
} else {
|
||||||
|
Err(io::Error::new(io::ErrorKind::Other, "error"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
use libarchive3_sys::ffi;
|
|
||||||
use super::builder::Builder;
|
use super::builder::Builder;
|
||||||
use crate::read::{Handle, Archive};
|
use crate::error::ArchiveError;
|
||||||
|
use crate::read::{Archive, Handle};
|
||||||
|
use libarchive3_sys::ffi;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use crate::error::ArchiveError;
|
|
||||||
|
|
||||||
const BLOCK_SIZE: usize = 10240;
|
const BLOCK_SIZE: usize = 10240;
|
||||||
|
|
||||||
|
@ -32,9 +32,7 @@ impl Drop for ArchiveFile {
|
||||||
|
|
||||||
impl Archive for ArchiveFile {
|
impl Archive for ArchiveFile {
|
||||||
fn new(handle: *mut ffi::Struct_archive) -> Self {
|
fn new(handle: *mut ffi::Struct_archive) -> Self {
|
||||||
Self {
|
Self { handle }
|
||||||
handle
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open<P: AsRef<Path>>(mut builder: Builder, path: P) -> crate::Result<Self> {
|
fn open<P: AsRef<Path>>(mut builder: Builder, path: P) -> crate::Result<Self> {
|
||||||
|
|
|
@ -1,15 +1,21 @@
|
||||||
mod builder;
|
mod builder;
|
||||||
|
mod entries;
|
||||||
mod file;
|
mod file;
|
||||||
|
|
||||||
|
pub use builder::Builder;
|
||||||
|
|
||||||
use crate::archive::Handle;
|
use crate::archive::Handle;
|
||||||
use builder::Builder;
|
use entries::Entries;
|
||||||
use std::path::Path;
|
|
||||||
use libarchive3_sys::ffi;
|
use libarchive3_sys::ffi;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
// Represents a read view of an archive
|
// Represents a read view of an archive
|
||||||
pub trait Archive: Handle + Sized {
|
pub trait Archive: Handle + Sized {
|
||||||
fn new(handle: *mut ffi::Struct_archive) -> Self;
|
fn new(handle: *mut ffi::Struct_archive) -> Self;
|
||||||
|
|
||||||
fn open<P: AsRef<Path>>(builder: Builder, path: P) -> crate::Result<Self>;
|
fn open<P: AsRef<Path>>(builder: Builder, path: P) -> crate::Result<Self>;
|
||||||
// entries
|
|
||||||
|
fn entries<'a>(&'a mut self) -> Entries<'a, Self> {
|
||||||
|
Entries::new(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
mod manager;
|
||||||
|
|
||||||
use axum::extract::{BodyStream, Path, State};
|
use axum::extract::{BodyStream, Path, State};
|
||||||
use axum::http::StatusCode;
|
use axum::http::StatusCode;
|
||||||
use axum::response::IntoResponse;
|
use axum::response::IntoResponse;
|
||||||
|
@ -6,6 +8,10 @@ use axum::Router;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use futures::TryFutureExt;
|
use futures::TryFutureExt;
|
||||||
use futures::TryStreamExt;
|
use futures::TryStreamExt;
|
||||||
|
use libarchive::archive::Entry;
|
||||||
|
use libarchive::read::Archive;
|
||||||
|
use libarchive::read::Builder;
|
||||||
|
use std::io::Read;
|
||||||
use tokio::{fs, io, io::AsyncWriteExt};
|
use tokio::{fs, io, io::AsyncWriteExt};
|
||||||
use tower_http::services::ServeDir;
|
use tower_http::services::ServeDir;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
@ -46,5 +52,27 @@ async fn post_package_archive(
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut builder = Builder::new();
|
||||||
|
builder
|
||||||
|
.support_format(libarchive::archive::ReadFormat::Tar)
|
||||||
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||||
|
builder
|
||||||
|
.support_filter(libarchive::archive::ReadFilter::All)
|
||||||
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||||
|
let mut ar = builder
|
||||||
|
.open_file(&path)
|
||||||
|
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||||
|
|
||||||
|
for entry in ar.entries() {
|
||||||
|
let mut entry = entry.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||||
|
|
||||||
|
if entry.pathname() == ".PKGINFO" {
|
||||||
|
let mut buffer = String::new();
|
||||||
|
entry.read_to_string(&mut buffer);
|
||||||
|
|
||||||
|
println!("{}", buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue