Pithos library
pithos_lib is the public Rust API for creating, opening, reading, extending, extracting, and adapting Pithos archives. It has no network client or transport policy. Cargo package versioning is separate.
Installation
Add the crate to an application using Rust 1.89 or newer:
[]
= "0.8"
The default features ro-crate and crypt4gh enable the RO-Crate conversion and Crypt4GH
export adapters. Use default-features = false to build only the archive format, reader,
writer and Linux filesystem operations.
Create an archive
A base archive needs no keys and accepts only local, uncompressed, unencrypted content:
use ;
use File;
This example encrypts a local file for its owner. The recipient public key is derived from the private key only for a self-contained example; production applications should provide the intended recipients' public keys.
use ;
use PrivateKey;
use File;
See examples/create.rs for the maintained version and the CLI guide for a command-line workflow.
Public API
- Create archives with
archive::ArchiveWriter,archive::WriteOptions, andcryptokeys. - Open an immutable
archive::Archivefrom asource::ArchiveSource, such assource::FileSourceorsource::MemorySource. - Read a complete entry with
copy_toor a checked range withcopy_range_to. - Use
fs::extract,fs::append_files,fs::grant_readers, andfs::ingestfor Linux host operations. - Use
adapters::ro_cratefor local directory/ZIP conversion andadapters::crypt4gh::exportfor Crypt4GH output. - Seal parts of one file independently with
archive::PieceEncoderand join the stored parts later witharchive::compose, which opens no key. KeepComposition::metadata_digestin trusted storage and pass it toOpenOptions::with_expected_metadata_digest.
Compiled examples are included with the package: create, open_list, read_ranges, extract, append, grant_readers, ro_crate, and crypt4gh. They are local-only and return errors to their caller.
The typed archive API deliberately keeps old model, helper, and internal format access private. Use WriteOptions::base for plain output or WriteOptions::new for encrypted output.
Read and extract semantics
Opening validates archive structure and accessible metadata. Payload integrity is lazy: each block is verified when it is read. copy_to and copy_range_to do not write bytes from a failed block, but a generic sink can retain earlier verified blocks if a later block fails. PithosError::ContentUnavailable means the entry is present but no supplied key can access its content; it is different from an integrity or corruption error.
fs::extract is Linux-only. It walks destination components without following symlinks, stages regular-file output anonymously with Linux O_TMPFILE, and publishes without replacing an existing entry. The destination filesystem must support O_TMPFILE and linkat(AT_EMPTY_PATH); extraction can therefore fail on a collision rather than overwrite a destination.
Async reading
The optional async feature adds source::AsyncArchiveSource, archive::AsyncArchive and
archive::AsyncExternalBlockResolver. It depends only on futures-core and needs no specific
async runtime.
AsyncArchive::open(source, options, known_len)issues the header, footer and directory requests one after the other. Their count does not depend on the number of blocks. Pass the object length asknown_lento skip the length request.read_range(path, range)returns aStreamof verified plaintext chunks in file order.ReadLimitsbounds the outstanding requests and the bytes held for responses, decoding and ordered delivery. Dropping the stream cancels its outstanding requests.read_range_owned(path, range)takes the archive in anArcand returns anOwnedRangeStreamthat holds it. It reads likeread_range, with the same order, bounds and cancellation, but it isSend + 'static. A server handler can return it as a streaming response body, for example after mapping its error type.- The source must serve one immutable object revision for the open and every later read, and each response must have exactly the requested length.
- Decoding directories and blocks is CPU work.
openruns it inline, which suits only small archives. Pass aBlockingHooktoopen_with_hookto move it to a blocking pool, for example one that forwards totokio::task::spawn_blocking. - External blocks follow the rules of the synchronous reader: they are read only when both a resolver and an access policy are supplied, and the resolver checks the policy before its initial access and before every redirect.
A handler that shares one opened archive can return a body stream like this:
use Stream;
use AsyncArchive;
use PithosError;
use AsyncArchiveSource;
use Range;
use Arc;
RO-Crate ingestion
Load a directory or ZIP RO-Crate, then convert its retained source through a configured writer:
use ;
use ProcessingOptions;
# = read_ro_crate_directory?;
write_ro_crate?;
# Ok
# }
The upstream parser accepts RO-Crate 1.1 and 1.2 metadata without upstream validation or warning emission; Pithos then applies its own source, path, limit, metadata, and conversion policy. Conversion stores the inspected ro-crate-metadata.json bytes rather than reserializing the graph. ZIP conversion streams retained members and does not extract them first.
Memory wiping
Pithos wipes its protected internal key and transform buffers. They hold keys, key lists, and block content while Pithos chunks, compresses, encrypts, decrypts, decompresses and verifies it. Other buffers are not wiped. For example, MemorySource keeps the archive bytes in a plain Arc<[u8]>, which holds the plaintext of plain blocks. Plaintext that a read hands to the caller is the caller's to wipe. zstd internal allocations may retain plaintext after being freed.
Platform behavior
pithos_lib builds only on Linux, even with default-features = false. The Linux filesystem modules in fs and the Unix file source in source are always compiled.
Filesystem ingestion, extraction, append, and grants are Linux-only in 0.8. Append uses a cooperating-writer advisory lock and can request AppendDurability::SyncAll; it attempts to truncate a failed child directory, but it cannot promise rollback after an unrecoverable host or power failure.