add option for writing an archive's entries with a prefix

This commit is contained in:
Jamie Winsor
2016-01-12 00:00:30 -08:00
parent a069bd2a98
commit 39b37933d7
3 changed files with 37 additions and 16 deletions
+11 -2
View File
@@ -1,9 +1,10 @@
use std::default::Default;
use std::ffi::{CStr, CString};
use std::path::PathBuf;
use std::str;
use std::ffi::CStr;
use libarchive3_sys::ffi;
use error::ErrCode;
use error::{ArchiveResult, ErrCode};
pub enum ReadCompression {
All,
@@ -120,6 +121,14 @@ pub trait Entry {
fn size(&self) -> i64 {
unsafe { ffi::archive_entry_size(self.entry()) }
}
fn set_pathname(&mut self, path: PathBuf) -> ArchiveResult<()> {
unsafe {
let c_str = CString::new(path.to_str().unwrap()).unwrap();
ffi::archive_entry_set_pathname(self.entry(), c_str.as_ptr());
}
Ok(())
}
}
pub enum ExtractOption {
+17 -6
View File
@@ -94,14 +94,19 @@ impl Disk {
}
// * Failures - HeaderPosition
pub fn write<T: Reader>(&self, reader: &mut T) -> ArchiveResult<()> {
pub fn write<T: Reader>(&self, reader: &mut T, prefix: Option<&str>) -> ArchiveResult<usize> {
if reader.header_position() != 0 {
return Err(ArchiveError::HeaderPosition);
}
let mut bytes: usize = 0;
let mut write_pending: bool = false;
loop {
{
if let Some(entry) = reader.next_header() {
if let Some(pfx) = prefix {
let path = Path::new(pfx).join(entry.pathname());
try!(entry.set_pathname(path));
}
match self.write_header(entry) {
Ok(()) => (),
Err(e) => return Err(e),
@@ -110,14 +115,20 @@ impl Disk {
write_pending = true
}
} else {
return Ok(());
break;
}
}
if write_pending {
try!(self.write_data(reader));
bytes += try!(self.write_data(reader));
write_pending = false;
}
}
unsafe {
match ffi::archive_write_finish_entry(self.handle()) {
ffi::ARCHIVE_OK => Ok(bytes),
_ => Err(ArchiveError::from(self as &Handle)),
}
}
}
pub fn close(&self) -> ArchiveResult<()> {
@@ -127,19 +138,19 @@ impl Disk {
ArchiveResult::from(self as &Handle)
}
fn write_data<T: Reader>(&self, reader: &T) -> ArchiveResult<()> {
fn write_data<T: Reader>(&self, reader: &T) -> ArchiveResult<usize> {
let mut buff = ptr::null();
let mut size = 0;
let mut offset = 0;
unsafe {
match ffi::archive_read_data_block(reader.handle(), &mut buff, &mut size, &mut offset) {
ffi::ARCHIVE_EOF => Ok(()),
ffi::ARCHIVE_EOF => Ok(size),
ffi::ARCHIVE_OK => {
if ffi::archive_write_data_block(self.handle, buff, size, offset) < 0 {
Err(ArchiveError::from(self as &Handle))
} else {
Ok(())
Ok(size)
}
}
_ => Err(ArchiveError::from(reader as &Handle)),
+9 -8
View File
@@ -35,11 +35,12 @@ fn read_archive_from_stream() {
builder.support_filter(ReadFilter::All).ok();
match builder.open_stream(f) {
Ok(mut reader) => {
println!("{:?}", reader.header_position());
assert_eq!(reader.header_position(), 0);
let writer = writer::Disk::new();
writer.write(&mut reader).ok();
println!("{:?}", reader.header_position());
assert_eq!(4, 4)
let count = writer.write(&mut reader, Some("/opt/bldr/fucks")).ok().unwrap();
assert_eq!(count, 14);
assert_eq!(reader.header_position(), 1024);
assert_eq!(4, 4);
},
Err(e) => {
println!("{:?}", e);
@@ -56,7 +57,7 @@ fn extracting_from_file() {
let mut reader = builder.open_file(tar).ok().unwrap();
println!("{:?}", reader.header_position());
let writer = writer::Disk::new();
writer.write(&mut reader).ok();
writer.write(&mut reader, None).ok();
println!("{:?}", reader.header_position());
assert_eq!(4, 4)
}
@@ -73,7 +74,7 @@ fn extracting_an_archive_with_options() {
opts.add(archive::ExtractOption::Time);
let writer = writer::Disk::new();
writer.set_options(&opts).ok();
writer.write(&mut reader).ok();
writer.write(&mut reader, None).ok();
println!("{:?}", reader.header_position());
assert_eq!(4, 4)
}
@@ -87,9 +88,9 @@ fn extracting_a_reader_twice() {
let mut reader = builder.open_file(tar).ok().unwrap();
println!("{:?}", reader.header_position());
let writer = writer::Disk::new();
writer.write(&mut reader).ok();
writer.write(&mut reader, None).ok();
println!("{:?}", reader.header_position());
match writer.write(&mut reader) {
match writer.write(&mut reader, None) {
Ok(_) => println!("oops"),
Err(_) => println!("nice")
}