Library API (libuc2)¶
libuc2 provides C99 functions for reading, extracting, and
compressing UC2 archives. The library is callback-based: callers supply
I/O and memory callbacks, making it suitable for embedded, DOS, and
freestanding environments.
Header: <uc2/libuc2.h>
Archive Reading¶
-
int uc2_identify(void *magic, unsigned magic_size)¶
Check whether a buffer contains a UC2 archive header.
- Parameters:
magic – Pointer to the first 4-21 bytes of the file.
magic_size – Number of bytes available.
- Returns:
1if UC2,0if not,-1if more bytes needed.
-
uc2_handle uc2_open(struct uc2_io *io, void *io_ctx)¶
Open a UC2 archive. The caller provides I/O callbacks via
uc2_io. ReturnsNULLon allocation failure.
-
uc2_handle uc2_close(uc2_handle h)¶
Close the archive and free all resources. Always returns
NULL.
Directory Enumeration¶
-
int uc2_read_cdir(uc2_handle h, struct uc2_entry *entry)¶
Read the next central directory entry.
- Returns:
UC2_End(0): end of directory, entry not filled.UC2_BareEntry(1): entry filled, no tags.UC2_TaggedEntry(3): entry filled, calluc2_get_tag()to read tags (long filename, etc.).Negative value on error.
Directories appear before their contents. Duplicate filenames are listed oldest-first.
-
int uc2_get_tag(uc2_handle h, struct uc2_entry *entry, char **tag, void **data, unsigned *data_len)¶
Read a tag from a tagged entry. Call repeatedly until it returns
UC2_End.
-
int uc2_finish_cdir(uc2_handle h, char label[12])¶
Read the archive tail and retrieve the volume label.
Extraction¶
-
int uc2_extract(uc2_handle h, struct uc2_xinfo *xi, unsigned size, int (*write)(void *ctx, const void *ptr, unsigned len), void *ctx)¶
Decompress a file entry. Call only after the entire central directory has been read. The write callback receives decompressed data in chunks.
Compression¶
-
int uc2_compress(int level, int (*read)(void *ctx, void *buf, unsigned len), void *read_ctx, int (*write)(void *ctx, const void *ptr, unsigned len), void *write_ctx, unsigned size, unsigned short *checksum_out, unsigned *compressed_size_out)¶
Compress raw data into a UC2 bitstream (no archive framing).
- Parameters:
level – Compression level: 2 = Fast, 3 = Normal, 4 = Tight (default), 5 = Ultra. Levels 6-9 select rANS Fast through Ultra.
read – Callback returning bytes read (0 at EOF, <0 on error).
write – Callback returning <0 on error.
size – Total input size in bytes.
checksum_out – Receives the Fletcher checksum of the input.
compressed_size_out – Receives the compressed size.
- Returns:
0 on success, negative
UC2_*error code on failure.
-
int uc2_compress_ex(int level, const void *master, unsigned master_size, int (*read)(void *ctx, void *buf, unsigned len), void *read_ctx, int (*write)(void *ctx, const void *ptr, unsigned len), void *write_ctx, unsigned size, unsigned short *checksum_out, unsigned *compressed_size_out)¶
Compress with a master-block dictionary prefix. The master data pre-fills the LZ77 sliding window, allowing back-references into the master for cross-file deduplication. Pass
NULL/0for no master (equivalent touc2_compress()).The CLI builds custom master blocks from input content. Those masters are themselves compressed with the built-in 49,152-byte SuperMaster.
-
int uc2_get_supermaster(void *buf, unsigned buf_size)¶
Decompress the built-in SuperMaster into buf (must be at least 49152 bytes). Returns
49152on success, negative error code on failure.
I/O Callbacks¶
-
struct uc2_io¶
-
int (*read)(void *io_ctx, unsigned pos, void *buf, unsigned len)¶
Read len bytes from the archive at offset pos into buf. Return number of bytes read (less if EOF), or negative on error.
-
void *(*alloc)(void *io_ctx, unsigned size)¶
Allocate memory. Return
NULLon failure.
-
void (*free)(void *io_ctx, void *ptr)¶
Free memory.
-
void (*warn)(void *io_ctx, char *fmt, ...)¶
Optional warning callback.
-
int (*read)(void *io_ctx, unsigned pos, void *buf, unsigned len)¶
Data Structures¶
-
struct uc2_entry¶
A directory entry.
-
unsigned dirid¶
Parent directory (0 = root).
-
unsigned id¶
Directory index (directories only).
-
unsigned size¶
Uncompressed file size.
-
unsigned csize¶
Compressed file size.
-
unsigned dos_time¶
DOS-format timestamp.
-
unsigned char attr¶
DOS file attributes.
-
char name[300]¶
Filename (UTF-8, NUL-terminated). Populated after tags are read.
-
unsigned dirid¶
Error Codes¶
Constant |
Meaning |
|---|---|
|
User callback refused to cooperate |
|
API called in wrong order |
|
Archive data is corrupt |
|
Unexpected end of data |
|
Feature not yet implemented |
|
Internal logic error |
Archive Writing¶
Header: <uc2/uc2_writer.h>. This GPL-3.0-or-later module uses hosted C99
malloc and tmpfile. It is separate from the optional LGPL legacy reader.
A writer owns its input spool and metadata; callbacks are used only during the
call that receives them. Free it with uc2_writer_free on every exit path.
struct uc2_writer_options options = UC2_WRITER_OPTIONS_INIT;
options.level = 4;
uc2_writer *writer = uc2_writer_create(&options);
if (!writer) return -1;
unsigned directory;
int rc = uc2_writer_add_directory(writer, 0, "docs", 0, 0, &directory);
if (rc == 0)
rc = uc2_writer_add_file(writer, directory, "notes.txt", 0, 0x20,
UC2_WRITER_UNKNOWN_SIZE, read_input, input_ctx);
if (rc == 0)
rc = uc2_writer_finish(writer, write_output, output_ctx);
/* Copy uc2_writer_error(writer) here if rc < 0. */
uc2_writer_free(writer);
return rc;
read_input(ctx, buffer, length) returns the number of bytes supplied,
zero at EOF, or a negative error. Short reads are allowed. A supplied file size
must match exactly; UC2_WRITER_UNKNOWN_SIZE reads to EOF. A limit violation
can consume one extra byte. write_output(ctx, data, length) must accept the
entire buffer and return a nonnegative value, or return a negative error.
The completed archive is assembled before the first output callback. Output
callback failure can leave partial output. For atomic destination replacement,
write to an exclusively created sibling temporary file, check flush and close,
then rename it. The CLI and Python UC2Writer implement this sequence.
An error poisons the writer: free it and start a new object. Successful finish
is one-shot. Objects must be used serially and callbacks must not reenter them.
Directory IDs come from uc2_writer_add_directory; parent zero is the root.
Files with the same name and parent become stored versions in insertion order.
Directory conflicts are rejected. Empty archives and directories are supported.
Names are single UTF-8 components representable in CP850, limited to 255 CP850
bytes and 299 UTF-8 bytes. Slash, backslash, colon, control characters, empty,
dot and dot-dot components are rejected. No silent truncation occurs.
Options default to level 4, 100,000 entries and UINT32_MAX total input bytes.
The maximum configurable entry count is 1,000,000. Input and archive size
limits are 32-bit; the raw central directory is capped at 64 MiB, directory
nesting at 64, and the CDC index at 1,048,576 chunks. Metadata grows with the
collection while payload buffers remain fixed. Source and archive temporary
files require disk space. The public header defines return values, metadata
fields, limits, and uc2_writer_get_stats.
Set options.chunked = 1 to share payload chunks across named files and
versions. Python exposes this as UC2Writer(..., chunked=True). This opt-in
format requires the full a11 or newer reader. See the chunk-sharing guide for the wire
format, reference limits and compressed-size accounting. Rebuild C callers
against the matching header when upgrading writer option/stat structures.