SArc is a simple archive format used primarily in YourSoftware applications. It currently officially supports 2 compression formats:
- LZMA
- LZ4
Note
SArc is a big-endian format, that is to say all multibyte integer and float values are stored in the big-endian byte order.
The format of SArc v3 goes as follows:
Magic value 0x53417263 (SArc)
Version 0x03
Block count UInt32
PGP signed flag UInt8
If PGP:
PGP signature size UInt16
PGP signature data
Per block:
File count UInt8
Per file:
File path - Null-terminated UTF-8 string (use forward-slashes `/` to seperate folders)
(the order of paths denotes the order files are stored in)
Decompressed block CRC32 UInt32
Compression enum UInt8
Decompressed block size UInt32
Compressed block size UInt32
Compressed:
Per file:
Data length UInt32
Data
SArc, UnSArc and SArcInfo are provided for you to download over on
the releases page.
These are simple packer, unpacker and signature verification command-line executables.
# Packs the current directory into 'out.sarc'
SArc
# Provide input and output paths:
SArc <input folder> <output archive>
UnSArc <input archive> <output folder>
# Provide a compression algorithm and level
SArc -c lzma:9 # LZMA prioritises size over speed and CPU usage (lzma:5 is default)
SArc -c lz4:5 # LZ4 prioritises speed and CPU usage over size and is excellent for streaming
SArc -c none:0
# Provide a target block size
SArc -b 8MiB # Faster streaming
SArc -b 128MiB # Balanced (default)
SArc -b 512MiB # Better compression
# Sign the archive using a PGP key
SArc --pgp-sign <private key> --pgp-sign-fp <key fingerprint>
SArc --pgp-sign <private key> --pgp-sign-fp <key fingerprint> --pgp-sign-ps <key passphrase>
# Print useful information about an archive
SArcInfo <input archive>
# Verify a signature (can be used in scripts: returns 0 if valid, -1 if invalid, and 1 for any other error)
SArcInfo <input archive> script-verify-signature <public key> <public key fingerprint>For more information, use --help.
Different versions of SArc will introduce breaking changes, and therefore prevent older archives being loaded in newer
applications and vice versa.
To combat this, you will need to unpack an archive using the UnSArc executable from the version it was created with,
and repack it with the SArc executable of the new version.
Tip
You can also do this to switch compression schemes.
Extensions are a way to increase the functionality of SArc. They are provided as extra headers / files, usually in a
subfolder called SArc.
Allows streaming of archives from the disk or the network. Streaming large archives can help reduce memory usage.
Note
Signing archives is not possible using streamed archives.
Use memory_archive.sign(...); on a memory-loaded archive to achieve this.
Caution
Streamed archives allocate new SArchiveFile objects on calls to get_file_by_path_const, remember to delete them,
or you'll leak memory.
Freeing SArchiveFiles obtained from a memory archive will cause dangling pointer issues, to differentiate between
the two, use archive.is_streamed().
// C++ Demo for SArc streaming extension
#include <SArc/Streaming.hpp>
using namespace SArc;
SArchiveStream streamed_archive("archive.sarc"); // Stream an archive from a file
const SArchiveFile *my_file = streamed_archive["hello_world.txt"];
delete my_file; // Make sure to free files created by streamed archives
void archive_magic(SArchive &archive);
archive_magic(streamed_archive); // SArchiveStream inherits SArchive
// Certain actions require an archive loaded in memory, like signing
SArchiveMemory memory_archive = streamed_archive.load_into_memory(); // Load the archive into memory
memory_archive.sign(key, "my_passphrase", {0x01, 0x02, ...});See the benchmarking page for more details on benefits from SArc streaming.
Allows for memory-efficient writing of archives without using a SArchive object. If you only need to pack archives
using streamed or very large data, this will drastically reduce memory usage.
Note
Signing archives is not possible using a BlockEncoder.
Create a SArchive object if you need to sign archives.
// C++ Demo for SArc BlockEncoder extension
#include <SArc/BlockEncoder.hpp>
using namespace SArc;
BlockEncoder sarc_encoder("archive.sarc"); // Write an archive to a file
sarc_encoder.start_block();
sarc_encoder.block_add_file_path("hello_world.txt");
sarc_encoder.block_add_file_path("other_file.txt");
// File data must be added in the same order as file paths were added
bytes_t data;
data.resize(13);
std::memcpy(data.data(), "Hello, World!", 13);
sarc_encoder.block_add_file_data(data);
std::memcpy(data.data(), "Other file...", 13);
sarc_encoder.block_add_file_data(data);
sarc_encoder.end_block();