1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
//! A library for reading and writing [CPIO
//! archives](https://en.wikipedia.org/wiki/Cpio).
//!
//! CPIO archives can be in any of several
//! [formats](https://www.gnu.org/software/cpio/manual/cpio.html#format). For
//! now, this library only supports the `newc` (SVR4) format.
use std::io;
use std::iter::Iterator;
pub mod newc;
pub use newc::Builder as NewcBuilder;
pub use newc::Reader as NewcReader;
/// Creates a new CPIO archive.
pub fn write_cpio<I, RS, W>(inputs: I, output: W) -> io::Result<W>
where
I: Iterator<Item = (NewcBuilder, RS)> + Sized,
RS: io::Read + io::Seek,
W: io::Write,
{
let output = inputs
.enumerate()
.try_fold(output, |output, (idx, (builder, mut input))| {
// If the output is valid, try to write the next input file
// Grab the length of the input file
let len = input.seek(io::SeekFrom::End(0))?;
input.seek(io::SeekFrom::Start(0))?;
// Create our writer fp with a unique inode number
let mut fp = builder.ino(idx as u32).write(output, len as u32);
// Write out the file
io::copy(&mut input, &mut fp)?;
// And finish off the input file
fp.finish()
})?;
newc::trailer(output)
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Cursor;
#[test]
fn test_multi_file() {
// Set up our input files
let mut input = vec![
(
NewcBuilder::new("./hello_world")
.uid(1000)
.gid(1000)
.mode(0o100644),
Cursor::new("Hello, World".to_string()),
),
(
NewcBuilder::new("./hello_world2")
.uid(1000)
.gid(1000)
.mode(0o100644),
Cursor::new("Hello, World 2".to_string()),
),
];
// Set up our output file
let output = Cursor::new(vec![]);
// Write out the CPIO archive
let _ = write_cpio(input.drain(..), output).unwrap();
}
}