Add Archive
struct to tar
This commit is contained in:
parent
a53cb726f9
commit
405ffd194f
109
tar/src/lib.rs
109
tar/src/lib.rs
@ -1,3 +1,5 @@
|
|||||||
|
use std::{fs::File, io::{self, BufReader}};
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
mod header;
|
mod header;
|
||||||
mod node;
|
mod node;
|
||||||
@ -10,3 +12,110 @@ pub use {
|
|||||||
pub struct Archive {
|
pub struct Archive {
|
||||||
pub nodes: Vec<Node>,
|
pub nodes: Vec<Node>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Archive {
|
||||||
|
/// Write out a vector of `TarNodes` to a file or something that implements ``std::io::Write`` and ``std::io::Copy``.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::fs::File;
|
||||||
|
/// use tar::tar::TarFile;
|
||||||
|
///
|
||||||
|
/// let data = Archive::new("test/1.txt".to_string()).unwrap();
|
||||||
|
///
|
||||||
|
/// let out = File::create("test/2.tar".to_string()).unwrap();
|
||||||
|
/// data.write(&out).unwrap();
|
||||||
|
/// ```
|
||||||
|
pub fn write<T: io::Write + Copy>(self, mut input: T) -> Result<usize, Error> {
|
||||||
|
let mut written = 0;
|
||||||
|
for f in self.nodes.clone() {
|
||||||
|
written += f.write(input)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Complete the write with 18 blocks of 512 ``0x00`` bytes per the specification */
|
||||||
|
if !self.nodes.is_empty() {
|
||||||
|
input.write_all(&[0; 9216])?;
|
||||||
|
written += 9216;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(written)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new `TarFile` struct and initialize it with a `filename` file. This will read in the file to
|
||||||
|
/// the `TarFile` struct as a `TarNode`.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use tar::Archive;
|
||||||
|
///
|
||||||
|
/// let data = Archive::new("test/1.txt".to_string()).unwrap();
|
||||||
|
/// ```
|
||||||
|
pub fn new(filename: String) -> Result<Self, Error> {
|
||||||
|
Ok(Self {
|
||||||
|
nodes: vec![Node::read_file_to_tar(filename)?],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Append another file to the `TarFile.file` vector. This adds a file to the internal representation of the tar file.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use tar::Archive;
|
||||||
|
///
|
||||||
|
/// let mut data = Archive::new("test/1.txt".to_string()).unwrap();
|
||||||
|
/// data.append("test/1.txt".to_string()).unwrap();
|
||||||
|
/// ```
|
||||||
|
pub fn append(&mut self, filename: String) -> Result<(), Error> {
|
||||||
|
self.nodes.push(Node::read_file_to_tar(filename)?);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Open and load an external tar file into the internal `TarFile` struct. This parses and loads up all the files
|
||||||
|
/// contained within the external tar file.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use tar::Archive;
|
||||||
|
///
|
||||||
|
/// Archive::open("test/1.tar".to_string()).unwrap();
|
||||||
|
/// ```
|
||||||
|
pub fn open(filename: String) -> Result<Self, Error> {
|
||||||
|
let file = File::open(&filename)?;
|
||||||
|
let mut reader = BufReader::new(file);
|
||||||
|
let mut out = Self {
|
||||||
|
nodes: Vec::<Node>::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
while let Ok(t) = Node::read(&mut reader) {
|
||||||
|
out.nodes.push(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove the first file from the Tar that matches the filename and path.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use minitar::tar::TarFile;
|
||||||
|
///
|
||||||
|
/// let mut data = TarFile::new("test/1.tar".to_string()).unwrap();
|
||||||
|
/// data.remove("test/1.tar".to_string()).unwrap();
|
||||||
|
/// ```
|
||||||
|
pub fn remove(&mut self, filename: String) -> Result<bool, Error> {
|
||||||
|
let mut name = [0u8; 100];
|
||||||
|
name[..filename.len()].copy_from_slice(filename.as_bytes());
|
||||||
|
if let Some(i) = &self.nodes.iter().position(|x| x.header.fname == name) {
|
||||||
|
self.nodes.remove(*i);
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -67,11 +67,7 @@ impl Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a Node from in memory data, given the filename and metadata
|
/// Create a Node from in memory data, given the filename and metadata
|
||||||
pub fn read_data_to_tar(
|
pub fn read_data_to_tar(data: &[u8], filename: &str, meta: &Metadata) -> Result<Node, Error> {
|
||||||
data: &[u8],
|
|
||||||
filename: &str,
|
|
||||||
meta: &Metadata,
|
|
||||||
) -> Result<Node, Error> {
|
|
||||||
let header = Header::new_from_meta(filename, meta)?;
|
let header = Header::new_from_meta(filename, meta)?;
|
||||||
if header.link_indicator[0] != FileType::Normal as u8 {
|
if header.link_indicator[0] != FileType::Normal as u8 {
|
||||||
return Ok(Node {
|
return Ok(Node {
|
||||||
|
Loading…
Reference in New Issue
Block a user