add option for writing an archive's entries with a prefix
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user