Skip to main content

Crate smol_tar

Crate smol_tar 

Source
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§

AttrList
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 AsyncRead source.
TarRegularFile
Regular-file metadata paired with a reader for its payload bytes.
TarRegularFileReader
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§

DeviceKind
Device-node kind for TarDevice.
TarEntry
High-level tar entry representation used by TarReader and TarWriter.