Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
[package]
name = "libarchive"
version = "0.1.1"
edition = "2021"
authors = ["Jamie Winsor <reset@chef.io>"]
license = "Apache-2.0"
repository = "https://github.com/chef/libarchive-rust"
description = "A safe Rust API for authoring and extracting archives with libarchive"
keywords = ["libarchive", "archive", "tar", "zip"]

[dependencies]
libc = ">= 0.2.0"
libarchive3-sys = "0.1"
libc = "0.2.147"
libarchive3-sys = { git = "https://github.com/jerry73204/libarchive3-sys.git", branch = "rewrite-using-bindgen" }
8 changes: 4 additions & 4 deletions src/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use std::ffi::{CStr, CString};
use std::path::PathBuf;
use std::str;

use libarchive3_sys::ffi;
use error::ErrCode;
use crate::error::ErrCode;
use libarchive3_sys as ffi;

pub enum ReadCompression {
All,
Expand Down Expand Up @@ -104,7 +104,7 @@ pub enum FileType {
}

pub trait Handle {
unsafe fn handle(&self) -> *mut ffi::Struct_archive;
unsafe fn handle(&self) -> *mut ffi::archive;

fn err_code(&self) -> ErrCode {
let code = unsafe { ffi::archive_errno(self.handle()) };
Expand All @@ -121,7 +121,7 @@ pub trait Handle {
}

pub trait Entry {
unsafe fn entry(&self) -> *mut ffi::Struct_archive_entry;
unsafe fn entry(&self) -> *mut ffi::archive_entry;

fn filetype(&self) -> FileType {
unsafe {
Expand Down
10 changes: 5 additions & 5 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::archive;
use std::error;
use std::fmt;
use archive;

pub type ArchiveResult<T> = Result<T, ArchiveError>;

Expand Down Expand Up @@ -42,14 +42,14 @@ impl fmt::Display for ArchiveError {
}
}

impl<'a> From<&'a archive::Handle> for ArchiveError {
fn from(handle: &'a archive::Handle) -> ArchiveError {
impl<'a> From<&'a dyn archive::Handle> for ArchiveError {
fn from(handle: &'a dyn archive::Handle) -> ArchiveError {
ArchiveError::Sys(handle.err_code(), handle.err_msg())
}
}

impl<'a> From<&'a archive::Handle> for ArchiveResult<()> {
fn from(handle: &'a archive::Handle) -> ArchiveResult<()> {
impl<'a> From<&'a dyn archive::Handle> for ArchiveResult<()> {
fn from(handle: &'a dyn archive::Handle) -> ArchiveResult<()> {
match handle.err_code() {
ErrCode(0) => Ok(()),
_ => Err(ArchiveError::from(handle)),
Expand Down
3 changes: 0 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
extern crate libc;
extern crate libarchive3_sys;

pub mod archive;
pub mod error;
pub mod reader;
Expand Down
84 changes: 45 additions & 39 deletions src/reader.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
use std::any::Any;
use std::default::Default;
use std::error::Error;
use std::ffi::CString;
use std::io::{self, Read};
use std::mem;
use std::path::Path;
use std::ptr;
use std::slice;

use libarchive3_sys as ffi;
use libc::{c_void, ssize_t};
use libarchive3_sys::ffi;

use archive::{Entry, ReadCompression, ReadFilter, ReadFormat, Handle};
use error::{ArchiveResult, ArchiveError};
use crate::archive::{Entry, Handle, ReadCompression, ReadFilter, ReadFormat};
use crate::error::{ArchiveError, ArchiveResult};

const BLOCK_SIZE: usize = 10240;

unsafe extern "C" fn stream_read_callback(handle: *mut ffi::Struct_archive,
data: *mut c_void,
buff: *mut *const c_void)
-> ssize_t {
unsafe extern "C" fn stream_read_callback(
handle: *mut ffi::archive,
data: *mut c_void,
buff: *mut *const c_void,
) -> ssize_t {
let pipe: &mut Pipe = &mut *(data as *mut Pipe);
*buff = pipe.buffer.as_mut_ptr() as *mut c_void;
match pipe.read_bytes() {
Ok(size) => size as ssize_t,
Err(e) => {
let desc = CString::new(e.description()).unwrap();
let desc = CString::new(e.to_string()).unwrap();
ffi::archive_set_error(handle, e.raw_os_error().unwrap_or(0), desc.as_ptr());
-1 as ssize_t
}
}
}

pub trait Reader : Handle {
pub trait Reader: Handle {
fn entry(&mut self) -> &mut ReaderEntry;

fn header_position(&self) -> i64 {
Expand Down Expand Up @@ -64,27 +64,27 @@ pub trait Reader : Handle {
}

pub struct FileReader {
handle: *mut ffi::Struct_archive,
handle: *mut ffi::archive,
entry: ReaderEntry,
}

pub struct StreamReader {
handle: *mut ffi::Struct_archive,
handle: *mut ffi::archive,
entry: ReaderEntry,
_pipe: Box<Pipe>,
}

pub struct Builder {
handle: *mut ffi::Struct_archive,
handle: *mut ffi::archive,
consumed: bool,
}

pub struct ReaderEntry {
handle: *mut ffi::Struct_archive_entry,
handle: *mut ffi::archive_entry,
}

struct Pipe {
reader: Box<Read>,
reader: Box<dyn Read>,
buffer: Vec<u8>,
}

Expand All @@ -103,20 +103,20 @@ impl Pipe {

impl FileReader {
pub fn open<T: AsRef<Path>>(mut builder: Builder, file: T) -> ArchiveResult<Self> {
try!(builder.check_consumed());
builder.check_consumed()?;
let c_file = CString::new(file.as_ref().to_string_lossy().as_bytes()).unwrap();
unsafe {
match ffi::archive_read_open_filename(builder.handle(), c_file.as_ptr(), BLOCK_SIZE) {
ffi::ARCHIVE_OK => {
builder.consume();
Ok(Self::new(builder.handle()))
}
_ => Err(ArchiveError::from(&builder as &Handle)),
_ => Err(ArchiveError::from(&builder as &dyn Handle)),
}
}
}

fn new(handle: *mut ffi::Struct_archive) -> Self {
fn new(handle: *mut ffi::archive) -> Self {
FileReader {
handle: handle,
entry: ReaderEntry::default(),
Expand All @@ -125,7 +125,7 @@ impl FileReader {
}

impl Handle for FileReader {
unsafe fn handle(&self) -> *mut ffi::Struct_archive {
unsafe fn handle(&self) -> *mut ffi::archive {
self.handle
}
}
Expand All @@ -149,11 +149,13 @@ impl StreamReader {
unsafe {
let mut pipe = Box::new(Pipe::new(src));
let pipe_ptr: *mut c_void = &mut *pipe as *mut Pipe as *mut c_void;
match ffi::archive_read_open(builder.handle(),
pipe_ptr,
None,
Some(stream_read_callback),
None) {
match ffi::archive_read_open(
builder.handle(),
pipe_ptr,
None,
Some(stream_read_callback),
None,
) {
ffi::ARCHIVE_OK => {
let reader = StreamReader {
handle: builder.handle(),
Expand All @@ -165,15 +167,15 @@ impl StreamReader {
}
_ => {
builder.consume();
Err(ArchiveError::from(&builder as &Handle))
Err(ArchiveError::from(&builder as &dyn Handle))
}
}
}
}
}

impl Handle for StreamReader {
unsafe fn handle(&self) -> *mut ffi::Struct_archive {
unsafe fn handle(&self) -> *mut ffi::archive {
self.handle
}
}
Expand Down Expand Up @@ -234,7 +236,7 @@ impl Builder {
};
match result {
ffi::ARCHIVE_OK => Ok(()),
_ => ArchiveResult::from(self as &Handle),
_ => ArchiveResult::from(self as &dyn Handle),
}
}

Expand All @@ -259,10 +261,12 @@ impl Builder {
ReadFilter::ProgramSignature(prog, cb, size) => {
let c_prog = CString::new(prog).unwrap();
unsafe {
ffi::archive_read_support_filter_program_signature(self.handle,
c_prog.as_ptr(),
mem::transmute(cb),
size)
ffi::archive_read_support_filter_program_signature(
self.handle,
c_prog.as_ptr(),
mem::transmute(cb),
size,
)
}
}
ReadFilter::Rpm => unsafe { ffi::archive_read_support_filter_rpm(self.handle) },
Expand All @@ -271,7 +275,7 @@ impl Builder {
};
match result {
ffi::ARCHIVE_OK => Ok(()),
_ => ArchiveResult::from(self as &Handle),
_ => ArchiveResult::from(self as &dyn Handle),
}
}

Expand All @@ -297,17 +301,17 @@ impl Builder {
};
match result {
ffi::ARCHIVE_OK => Ok(()),
_ => ArchiveResult::from(self as &Handle),
_ => ArchiveResult::from(self as &dyn Handle),
}
}

pub fn open_file<T: AsRef<Path>>(self, file: T) -> ArchiveResult<FileReader> {
try!(self.check_consumed());
self.check_consumed()?;
FileReader::open(self, file)
}

pub fn open_stream<T: Any + Read>(self, src: T) -> ArchiveResult<StreamReader> {
try!(self.check_consumed());
self.check_consumed()?;
StreamReader::open(self, src)
}

Expand All @@ -325,7 +329,7 @@ impl Builder {
}

impl Handle for Builder {
unsafe fn handle(&self) -> *mut ffi::Struct_archive {
unsafe fn handle(&self) -> *mut ffi::archive {
self.handle
}
}
Expand Down Expand Up @@ -356,19 +360,21 @@ impl Default for Builder {
}

impl ReaderEntry {
pub fn new(handle: *mut ffi::Struct_archive_entry) -> Self {
pub fn new(handle: *mut ffi::archive_entry) -> Self {
ReaderEntry { handle: handle }
}
}

impl Default for ReaderEntry {
fn default() -> Self {
ReaderEntry { handle: ptr::null_mut() }
ReaderEntry {
handle: ptr::null_mut(),
}
}
}

impl Entry for ReaderEntry {
unsafe fn entry(&self) -> *mut ffi::Struct_archive_entry {
unsafe fn entry(&self) -> *mut ffi::archive_entry {
self.handle
}
}
Loading