From 39b37933d77f07d190b80a4e83ed63ddcff5693a Mon Sep 17 00:00:00 2001 From: Jamie Winsor Date: Tue, 12 Jan 2016 00:00:30 -0800 Subject: [PATCH] add option for writing an archive's entries with a prefix --- libraries/libarchive/src/archive.rs | 13 +++++++++++-- libraries/libarchive/src/writer.rs | 23 +++++++++++++++++------ libraries/libarchive/tests/lib.rs | 17 +++++++++-------- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/libraries/libarchive/src/archive.rs b/libraries/libarchive/src/archive.rs index e680965d..4fa3172a 100644 --- a/libraries/libarchive/src/archive.rs +++ b/libraries/libarchive/src/archive.rs @@ -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 { diff --git a/libraries/libarchive/src/writer.rs b/libraries/libarchive/src/writer.rs index 0942bdee..14e41b80 100644 --- a/libraries/libarchive/src/writer.rs +++ b/libraries/libarchive/src/writer.rs @@ -94,14 +94,19 @@ impl Disk { } // * Failures - HeaderPosition - pub fn write(&self, reader: &mut T) -> ArchiveResult<()> { + pub fn write(&self, reader: &mut T, prefix: Option<&str>) -> ArchiveResult { 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(&self, reader: &T) -> ArchiveResult<()> { + fn write_data(&self, reader: &T) -> ArchiveResult { 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)), diff --git a/libraries/libarchive/tests/lib.rs b/libraries/libarchive/tests/lib.rs index fcbd7acf..872e9472 100644 --- a/libraries/libarchive/tests/lib.rs +++ b/libraries/libarchive/tests/lib.rs @@ -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") }