mirror of
https://github.com/Drop-OSS/drop.git
synced 2026-07-23 00:12:53 +10:00
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::default::Default;
|
||||||
|
use std::ffi::{CStr, CString};
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::ffi::CStr;
|
|
||||||
|
|
||||||
use libarchive3_sys::ffi;
|
use libarchive3_sys::ffi;
|
||||||
use error::ErrCode;
|
use error::{ArchiveResult, ErrCode};
|
||||||
|
|
||||||
pub enum ReadCompression {
|
pub enum ReadCompression {
|
||||||
All,
|
All,
|
||||||
@@ -120,6 +121,14 @@ pub trait Entry {
|
|||||||
fn size(&self) -> i64 {
|
fn size(&self) -> i64 {
|
||||||
unsafe { ffi::archive_entry_size(self.entry()) }
|
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 {
|
pub enum ExtractOption {
|
||||||
|
|||||||
@@ -94,14 +94,19 @@ impl Disk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// * Failures - HeaderPosition
|
// * 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 {
|
if reader.header_position() != 0 {
|
||||||
return Err(ArchiveError::HeaderPosition);
|
return Err(ArchiveError::HeaderPosition);
|
||||||
}
|
}
|
||||||
|
let mut bytes: usize = 0;
|
||||||
let mut write_pending: bool = false;
|
let mut write_pending: bool = false;
|
||||||
loop {
|
loop {
|
||||||
{
|
{
|
||||||
if let Some(entry) = reader.next_header() {
|
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) {
|
match self.write_header(entry) {
|
||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
@@ -110,14 +115,20 @@ impl Disk {
|
|||||||
write_pending = true
|
write_pending = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Ok(());
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if write_pending {
|
if write_pending {
|
||||||
try!(self.write_data(reader));
|
bytes += try!(self.write_data(reader));
|
||||||
write_pending = false;
|
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<()> {
|
pub fn close(&self) -> ArchiveResult<()> {
|
||||||
@@ -127,19 +138,19 @@ impl Disk {
|
|||||||
ArchiveResult::from(self as &Handle)
|
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 buff = ptr::null();
|
||||||
let mut size = 0;
|
let mut size = 0;
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
match ffi::archive_read_data_block(reader.handle(), &mut buff, &mut size, &mut offset) {
|
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 => {
|
ffi::ARCHIVE_OK => {
|
||||||
if ffi::archive_write_data_block(self.handle, buff, size, offset) < 0 {
|
if ffi::archive_write_data_block(self.handle, buff, size, offset) < 0 {
|
||||||
Err(ArchiveError::from(self as &Handle))
|
Err(ArchiveError::from(self as &Handle))
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err(ArchiveError::from(reader as &Handle)),
|
_ => Err(ArchiveError::from(reader as &Handle)),
|
||||||
|
|||||||
@@ -35,11 +35,12 @@ fn read_archive_from_stream() {
|
|||||||
builder.support_filter(ReadFilter::All).ok();
|
builder.support_filter(ReadFilter::All).ok();
|
||||||
match builder.open_stream(f) {
|
match builder.open_stream(f) {
|
||||||
Ok(mut reader) => {
|
Ok(mut reader) => {
|
||||||
println!("{:?}", reader.header_position());
|
assert_eq!(reader.header_position(), 0);
|
||||||
let writer = writer::Disk::new();
|
let writer = writer::Disk::new();
|
||||||
writer.write(&mut reader).ok();
|
let count = writer.write(&mut reader, Some("/opt/bldr/fucks")).ok().unwrap();
|
||||||
println!("{:?}", reader.header_position());
|
assert_eq!(count, 14);
|
||||||
assert_eq!(4, 4)
|
assert_eq!(reader.header_position(), 1024);
|
||||||
|
assert_eq!(4, 4);
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("{:?}", e);
|
println!("{:?}", e);
|
||||||
@@ -56,7 +57,7 @@ fn extracting_from_file() {
|
|||||||
let mut reader = builder.open_file(tar).ok().unwrap();
|
let mut reader = builder.open_file(tar).ok().unwrap();
|
||||||
println!("{:?}", reader.header_position());
|
println!("{:?}", reader.header_position());
|
||||||
let writer = writer::Disk::new();
|
let writer = writer::Disk::new();
|
||||||
writer.write(&mut reader).ok();
|
writer.write(&mut reader, None).ok();
|
||||||
println!("{:?}", reader.header_position());
|
println!("{:?}", reader.header_position());
|
||||||
assert_eq!(4, 4)
|
assert_eq!(4, 4)
|
||||||
}
|
}
|
||||||
@@ -73,7 +74,7 @@ fn extracting_an_archive_with_options() {
|
|||||||
opts.add(archive::ExtractOption::Time);
|
opts.add(archive::ExtractOption::Time);
|
||||||
let writer = writer::Disk::new();
|
let writer = writer::Disk::new();
|
||||||
writer.set_options(&opts).ok();
|
writer.set_options(&opts).ok();
|
||||||
writer.write(&mut reader).ok();
|
writer.write(&mut reader, None).ok();
|
||||||
println!("{:?}", reader.header_position());
|
println!("{:?}", reader.header_position());
|
||||||
assert_eq!(4, 4)
|
assert_eq!(4, 4)
|
||||||
}
|
}
|
||||||
@@ -87,9 +88,9 @@ fn extracting_a_reader_twice() {
|
|||||||
let mut reader = builder.open_file(tar).ok().unwrap();
|
let mut reader = builder.open_file(tar).ok().unwrap();
|
||||||
println!("{:?}", reader.header_position());
|
println!("{:?}", reader.header_position());
|
||||||
let writer = writer::Disk::new();
|
let writer = writer::Disk::new();
|
||||||
writer.write(&mut reader).ok();
|
writer.write(&mut reader, None).ok();
|
||||||
println!("{:?}", reader.header_position());
|
println!("{:?}", reader.header_position());
|
||||||
match writer.write(&mut reader) {
|
match writer.write(&mut reader, None) {
|
||||||
Ok(_) => println!("oops"),
|
Ok(_) => println!("oops"),
|
||||||
Err(_) => println!("nice")
|
Err(_) => println!("nice")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user