Expand description
A minimal async streaming tar reader and writer.
The reader is fully streaming: TarReader yields TarEntry values from
any AsyncRead source with very little buffering. Regular file entries
expose their payload through TarRegularFile, which also implements
AsyncRead. To move on to the next entry, either read the file body to
the end or drop the file reader.
The writer is a Sink of TarEntry values and also
provides inherent TarWriter::write and TarWriter::finish helpers for
straightforward sequential writing without futures::sink::SinkExt.
Write entries to archive with TarWriter::write or futures::sink::SinkExt::send.
Finish the archive with TarWriter::finish or futures::sink::SinkExt::close
so the trailing zero blocks are emitted.
§Examples
Runtime selection:
[dependencies]
smol-tar = "0.1"[dependencies]
smol-tar = { version = "0.1", default-features = false, features = ["tokio"] }Reading an archive:
use smol_tar::{TarEntry, TarReader};
let data = Cursor::new(vec![0; 1024]);
let mut tar = TarReader::new(data);
while let Some(entry) = tar.next().await {
match entry? {
TarEntry::File(mut file) => {
println!("file: {} ({} bytes)", file.path(), file.size());
copy(&mut file, &mut sink()).await?;
}
TarEntry::Directory(dir) => {
println!("dir: {}", dir.path());
}
other => {
println!("other: {}", other.path());
}
}
}Writing an archive:
use smol_tar::{TarDirectory, TarEntry, TarRegularFile, TarWriter};
let sink = Cursor::new(Vec::<u8>::new());
let mut tar = TarWriter::new(sink);
tar.write(TarDirectory::new("bin/").into()).await?;
let body = Cursor::new(b"hello\n");
tar.write(
TarRegularFile::new(
"bin/hello.txt", 6, body,
).into()
).await?;
tar.finish().await?;Alongside the direct API, the writer also implements the composable
Sink interface:
use {
smol_tar::{TarDirectory, TarEntry, TarReader, TarRegularFile, TarWriter},
futures::{future, SinkExt, StreamExt, TryStreamExt},
};
let mut input = Cursor::new(Vec::<u8>::new());
let mut source = TarWriter::new(&mut input);
source.send(
TarDirectory::new("bin/").into()
).await?;
source.send(
TarRegularFile::new(
"bin/keep.txt", 5, Cursor::new(b"keep\n".as_ref())
).into()
).await?;
source.send(
TarRegularFile::new(
"share/skip.txt", 5, Cursor::new(b"skip\n".as_ref())
).into()
).await?;
source.send(
TarRegularFile::new(
"bin/run.sh", 8, Cursor::new(b"echo hi\n".as_ref())
).with_mode(0o755).into()
).await?;
source.close().await?;
input.set_position(0);
let mut output = Cursor::new(Vec::<u8>::new());
let mut filtered = TarWriter::new(&mut output);
TarReader::new(&mut input)
.try_filter(|entry| {
future::ready(entry.path().starts_with("bin/"))
})
.forward(&mut filtered)
.await?;
filtered.close().await?;
output.set_position(0);
let paths: Vec<String> = TarReader::new(output)
.map_ok(|entry| entry.path().to_string())
.try_collect()
.await?;
assert_eq!(paths, vec!["bin/", "bin/keep.txt", "bin/run.sh"]);§Supported formats
Reads:
- Old tar
- GNU tar
- POSIX ustar/pax
- GNU long names and long links
- PAX path metadata, timestamps, numeric ids, sizes, and extended attributes
Writes:
- POSIX ustar/pax
- PAX records for long paths, long link targets, timestamps, numeric ids, symbolic names, sizes, and extended attributes
§Not supported
- Sparse files and multi-volume archives
Structs§
- Attr
List - List of extended attributes stored in PAX records.
- TarDevice
- Device-node metadata stored in a tar archive.
- TarDirectory
- Directory metadata stored in a tar archive.
- TarFifo
- FIFO (named pipe) metadata stored in a tar archive.
- TarLink
- Hard-link entry stored in a tar archive.
- TarReader
- Streaming tar reader over an
AsyncReadsource. - TarRegular
File - Regular-file metadata paired with a reader for its payload bytes.
- TarRegular
File Reader - Async reader for the body of the current regular-file entry.
- TarSymlink
- Symbolic-link metadata stored in a tar archive.
- TarWriter
- Streaming tar writer that implements
future_sink::Sink<TarEntry<...>>.
Enums§
- Device
Kind - Device-node kind for
TarDevice. - TarEntry
- High-level tar entry representation used by
TarReaderandTarWriter.