release: restore ZUPT and harden source-only 5.2.2
This commit is contained in:
parent
74e393ba3e
commit
ff99770bd0
205 changed files with 19627 additions and 13215 deletions
211
include/zupt.h
211
include/zupt.h
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Zupt — Backup-oriented compression with AES-256 encryption
|
||||
* ZUPT — Backup-oriented compression with AES-256 encryption
|
||||
* Copyright (c) 2026 Cristian Cezar Moisés
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
|
@ -15,12 +15,79 @@
|
|||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#include <wchar.h>
|
||||
#define ZUPT_PATH_SEP '\\'
|
||||
#define zupt_mkdir(p) _mkdir(p)
|
||||
|
||||
static inline wchar_t *zupt_win_utf8_to_wide_alloc(const char *text) {
|
||||
if (!text) return NULL;
|
||||
int length = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
|
||||
text, -1, NULL, 0);
|
||||
if (length <= 0) return NULL;
|
||||
wchar_t *wide = (wchar_t *)malloc((size_t)length * sizeof(wchar_t));
|
||||
if (!wide || !MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
|
||||
text, -1, wide, length)) {
|
||||
free(wide);
|
||||
return NULL;
|
||||
}
|
||||
return wide;
|
||||
}
|
||||
|
||||
static inline char *zupt_win_wide_to_utf8_alloc(const wchar_t *text) {
|
||||
if (!text) return NULL;
|
||||
int length = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
|
||||
text, -1, NULL, 0, NULL, NULL);
|
||||
if (length <= 0) return NULL;
|
||||
char *utf8 = (char *)malloc((size_t)length);
|
||||
if (!utf8 || !WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
|
||||
text, -1, utf8, length, NULL, NULL)) {
|
||||
free(utf8);
|
||||
return NULL;
|
||||
}
|
||||
return utf8;
|
||||
}
|
||||
|
||||
static inline FILE *zupt_win_fopen_utf8(const char *path, const char *mode) {
|
||||
wchar_t *wide_path = zupt_win_utf8_to_wide_alloc(path);
|
||||
wchar_t *wide_mode = zupt_win_utf8_to_wide_alloc(mode);
|
||||
if (!wide_path || !wide_mode) {
|
||||
free(wide_path);
|
||||
free(wide_mode);
|
||||
return NULL;
|
||||
}
|
||||
FILE *stream = _wfopen(wide_path, wide_mode);
|
||||
free(wide_path);
|
||||
free(wide_mode);
|
||||
return stream;
|
||||
}
|
||||
|
||||
static inline DWORD zupt_win_get_attributes_utf8(const char *path) {
|
||||
wchar_t *wide = zupt_win_utf8_to_wide_alloc(path);
|
||||
if (!wide) return INVALID_FILE_ATTRIBUTES;
|
||||
DWORD attributes = GetFileAttributesW(wide);
|
||||
free(wide);
|
||||
return attributes;
|
||||
}
|
||||
|
||||
static inline int zupt_win_mkdir_utf8(const char *path) {
|
||||
wchar_t *wide = zupt_win_utf8_to_wide_alloc(path);
|
||||
if (!wide) return -1;
|
||||
int result = _wmkdir(wide);
|
||||
free(wide);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Project path strings are UTF-8 on every platform. Call this wrapper
|
||||
* explicitly; never rewrite the C library's fopen in consumer code. */
|
||||
static inline FILE *zupt_fopen_path(const char *path, const char *mode) {
|
||||
return zupt_win_fopen_utf8(path, mode);
|
||||
}
|
||||
#define zupt_mkdir(p) zupt_win_mkdir_utf8(p)
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
|
@ -28,29 +95,29 @@
|
|||
#include <unistd.h>
|
||||
#define ZUPT_PATH_SEP '/'
|
||||
#define zupt_mkdir(p) mkdir(p, 0755)
|
||||
static inline FILE *zupt_fopen_path(const char *path, const char *mode) {
|
||||
return fopen(path, mode);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ─── Product identity ─────────────────────────────────────────────
|
||||
*
|
||||
* v3.0.0 (INPI Brasil trademark rename):
|
||||
* - Product name is now "VaptVupt" (was "Zupt"). The earlier name
|
||||
* conflicted with a software trademark already registered at INPI
|
||||
* Brasil under "Zupt".
|
||||
* - File extension stays `.zupt` for archive-format continuity:
|
||||
* v1.0–v2.4.x archives remain readable, the magic bytes
|
||||
* `\x5A\x55\x50\x54\x1A\x00` ("ZUPT" + sub-version) are unchanged.
|
||||
* - C identifier prefix stays `zupt_` / `ZUPT_` for ABI continuity
|
||||
* with libzuptsdk and existing callers. Only user-visible strings
|
||||
* (binary name, banner, help text, package names) change.
|
||||
* - The binary is now `vaptvupt`. Distro packages may ship a
|
||||
* compatibility symlink `zupt -> vaptvupt` for one major version.
|
||||
* v5.2.2 (product identity restored):
|
||||
* - The public product and primary command are again "ZUPT" and `zupt`.
|
||||
* - On-disk compatibility is deliberately unchanged: magic remains
|
||||
* "ZUPT", the archive extension remains .zupt, and format version
|
||||
* remains 1.6.
|
||||
* - Internal zupt_* symbols, SDK identifiers, codec IDs, and the bundled
|
||||
* VaptVupt codec ABI remain unchanged.
|
||||
* - Distributors may offer `vaptvupt -> zupt` only as an explicit
|
||||
* compatibility alias for scripts written for releases 3.0.0--5.2.1.
|
||||
*/
|
||||
#define ZUPT_PRODUCT_NAME "VaptVupt"
|
||||
#define ZUPT_PRODUCT_NAME_LC "vaptvupt" /* lowercase: binary name */
|
||||
#define ZUPT_PRODUCT_NAME "ZUPT"
|
||||
#define ZUPT_PRODUCT_NAME_LC "zupt" /* lowercase: binary name */
|
||||
#define ZUPT_PRODUCT_EXTENSION ".zupt" /* on-disk archive extension (kept stable) */
|
||||
#define ZUPT_PRODUCT_TAGLINE "Post-quantum backup compression"
|
||||
|
||||
#define ZUPT_VERSION_STRING "5.2.1"
|
||||
#define ZUPT_VERSION_STRING "5.2.2"
|
||||
/* Vendored codec release (upstream tag) — single source for display strings.
|
||||
* The codec's own VV_VERSION_* is its internal API version, not the release. */
|
||||
#define ZUPT_CODEC_RELEASE "2.65.3"
|
||||
|
|
@ -67,10 +134,13 @@
|
|||
* to keep the field stable across format-version transitions. Both bytes are
|
||||
* structurally validated by read_footer().
|
||||
*
|
||||
* Read path falls back to v1.4 layout (no trailer) when the footer magic is
|
||||
* found at EOF-32 instead of EOF-64. */
|
||||
* The reader can identify a legacy v1.4 layout at EOF-32, but refuses it by
|
||||
* default because the missing trailer is indistinguishable from an integrity
|
||||
* downgrade. Trusted old archives require --allow-legacy-no-ait. */
|
||||
#define ZUPT_AIT_SIZE 32
|
||||
#define ZUPT_AIT_MAC_INPUT_LEN (sizeof(zupt_archive_header_t) + 24)
|
||||
#define ZUPT_ARCHIVE_HEADER_SIZE 64u
|
||||
#define ZUPT_FOOTER_SIZE 32u
|
||||
#define ZUPT_AIT_MAC_INPUT_LEN (ZUPT_ARCHIVE_HEADER_SIZE + 24u)
|
||||
|
||||
#define ZUPT_MAGIC_0 0x5A
|
||||
#define ZUPT_MAGIC_1 0x55
|
||||
|
|
@ -83,6 +153,11 @@
|
|||
|
||||
#define ZUPT_MAX_PATH 4096
|
||||
#define ZUPT_MAX_FILES 2000000
|
||||
/* A decoded index entry contains a fixed-size path buffer. Cap aggregate
|
||||
* allocation independently of the wire count so a compact malicious index
|
||||
* cannot request several gigabytes of zeroed memory. */
|
||||
#define ZUPT_MAX_INDEX_ALLOC_BYTES (256u * 1024u * 1024u)
|
||||
#define ZUPT_MIN_INDEX_ENTRY_BYTES 47u
|
||||
#define ZUPT_DEFAULT_BLOCK_SZ (4 * 1024 * 1024)
|
||||
#define ZUPT_MIN_BLOCK_SZ (64 * 1024)
|
||||
#define ZUPT_MAX_BLOCK_SZ (256 * 1024 * 1024)
|
||||
|
|
@ -97,12 +172,14 @@
|
|||
#define ZUPT_FLAG_DEDUP (1u << 7) /* Block-level deduplication enabled */
|
||||
#define ZUPT_FLAG_AAD_SEQ (1u << 8) /* MAC binds block_seq as AAD (anti-reorder) */
|
||||
#define ZUPT_FLAG_AAD_PREFACE (1u << 9) /* v1.6: MAC also binds per-block frame preface (F-09) */
|
||||
#define ZUPT_FLAG_AUTH_DEDUP_REFS (1u << 10) /* Dedup offsets carry per-block authentication */
|
||||
#define ZUPT_FLAG_DISK_CONTENT_HASH (1u << 11) /* Disk index hashes restored bytes */
|
||||
|
||||
/* Encryption types (stored in encryption header block) */
|
||||
#define ZUPT_ENC_PBKDF2 0x01 /* Password-based: PBKDF2 → AES-256-CTR + HMAC */
|
||||
#define ZUPT_ENC_PQ_HYBRID 0x02 /* ML-KEM-768 + X25519 hybrid KEM (legacy XOR+SHA3) */
|
||||
#define ZUPT_ENC_PQ_SDK_V2 0x03 /* libzuptsdk v2 header: HKDF combiner + commitment + HPKE binding */
|
||||
#define ZUPT_ENC_PW_ARGON2 0x04 /* Password-based via libzuptsdk: Argon2id + XChaCha20-Poly1305 */
|
||||
#define ZUPT_ENC_PQ_SDK_V2 0x03 /* libvuptsdk v2 header: HKDF combiner + commitment + HPKE binding */
|
||||
#define ZUPT_ENC_PW_ARGON2 0x04 /* Password-based via libvuptsdk: Argon2id + XChaCha20-Poly1305 */
|
||||
#define ZUPT_ENC_PQ_BOX_V1 0x05 /* libpqvaptvupt sealed box: HKDF-SHA256 domain-separated combiner */
|
||||
#define ZUPT_ENC_PQ_ONLY 0x06 /* Full post-quantum: ML-KEM-768 only (no X25519), SHA3-512 KDF (v4.2.0) */
|
||||
|
||||
|
|
@ -123,12 +200,12 @@
|
|||
* descriptor is covered by the archive-integrity trailer (F-08), so it
|
||||
* cannot be stripped or forged without failing authentication.
|
||||
*
|
||||
* Profile 0 (implicit, absent byte) == the historical libzuptsdk
|
||||
* Profile 0 (implicit, absent byte) == the historical libvuptsdk
|
||||
* "MODERATE" Argon2id preset reached via zuptsdk_easy_derive_key.
|
||||
* Profile 1 is the same derivation with the descriptor made explicit so
|
||||
* future profiles (should the cost change) get distinct IDs. */
|
||||
#define ZUPT_ARGON2_PROFILE_LEGACY 0x00 /* implicit: pre-3.4.0, no descriptor byte */
|
||||
#define ZUPT_ARGON2_PROFILE_MODERATE 0x01 /* explicit: libzuptsdk MODERATE preset */
|
||||
#define ZUPT_ARGON2_PROFILE_MODERATE 0x01 /* explicit: libvuptsdk MODERATE preset */
|
||||
#define ZUPT_ARGON2_HDR_LEN_V1 33 /* [type|salt16|nonce16] */
|
||||
#define ZUPT_ARGON2_HDR_LEN_V2 34 /* + [profile1] */
|
||||
|
||||
|
|
@ -136,7 +213,7 @@
|
|||
#define ZUPT_BLOCK_DATA 0x00
|
||||
#define ZUPT_BLOCK_INDEX 0x02
|
||||
#define ZUPT_BLOCK_ENC_HEADER 0x03
|
||||
#define ZUPT_BLOCK_DEDUP_REF 0x04 /* Dedup reference: payload = 8B offset of original block */
|
||||
#define ZUPT_BLOCK_DEDUP_REF 0x04 /* Dedup reference; authenticated v5.2.2 payload also carries source AAD sequence */
|
||||
#define ZUPT_BLOCK_COMMENT 0x05 /* v2.4.3: free-form UTF-8 comment, encrypted same as data blocks */
|
||||
|
||||
#define ZUPT_MAX_COMMENT_LEN 4096 /* Maximum comment payload size (bytes). */
|
||||
|
|
@ -270,7 +347,7 @@ typedef struct {
|
|||
int level; uint32_t block_size; uint16_t codec_id;
|
||||
int verbose, encrypt, quiet, solid, threads;
|
||||
int pq_mode; /* 1 = post-quantum hybrid KEM mode */
|
||||
int sdk_mode; /* 1 = use libzuptsdk-backed v3 crypto (HKDF combiner + commitment + HPKE) */
|
||||
int sdk_mode; /* 1 = use libvuptsdk-backed v3 crypto (HKDF combiner + commitment + HPKE) */
|
||||
int box_mode; /* 1 = libpqvaptvupt sealed-box mode (ZUPT_ENC_PQ_BOX_V1) */
|
||||
int pqonly_mode; /* 1 = full post-quantum mode: ML-KEM-768 only (ZUPT_ENC_PQ_ONLY) */
|
||||
int dedup; /* 1 = block-level deduplication enabled */
|
||||
|
|
@ -345,7 +422,7 @@ static inline void zupt_secure_wipe(void *ptr, size_t len) {
|
|||
|
||||
static inline int zupt_is_regular_file(const char *path) {
|
||||
#ifdef _WIN32
|
||||
DWORD attr = GetFileAttributesA(path);
|
||||
DWORD attr = zupt_win_get_attributes_utf8(path);
|
||||
if (attr == INVALID_FILE_ATTRIBUTES) return 0;
|
||||
return !(attr & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE |
|
||||
FILE_ATTRIBUTE_REPARSE_POINT));
|
||||
|
|
@ -396,10 +473,11 @@ void zupt_hmac_sha256_init(zupt_hmac_ctx *c, const uint8_t *key, size_t klen);
|
|||
void zupt_hmac_sha256_update(zupt_hmac_ctx *c, const uint8_t *data, size_t dlen);
|
||||
void zupt_hmac_sha256_final(zupt_hmac_ctx *c, uint8_t mac[32]);
|
||||
|
||||
/* Constant-time buffer equality. Returns 1 if equal, 0 otherwise, in
|
||||
* time dependent only on n (not contents / mismatch position). The single
|
||||
* audited MAC-tag comparison primitive; timing-verified by the
|
||||
* dudect-style test in tests/test_ct_timing.c. CT-REQUIRED. */
|
||||
/* Constant-time-intended buffer equality. Returns 1 if equal, 0 otherwise.
|
||||
* The source has a fixed-length OR-accumulate loop without an intended
|
||||
* content-dependent exit or access. The dudect-style regression in
|
||||
* tests/test_ct_timing.c measures exact builds when its control is conclusive;
|
||||
* it is not a formal guarantee about compiler output. CT-REQUIRED. */
|
||||
int zupt_ct_memeq(const void *a, const void *b, size_t n);
|
||||
void zupt_pbkdf2_sha256(const uint8_t *pw, size_t pwlen, const uint8_t *salt, size_t slen, uint32_t iter, uint8_t *out, size_t olen);
|
||||
void zupt_aes256_ctr(const uint8_t key[32], const uint8_t nonce[16], const uint8_t *in, uint8_t *out, size_t len);
|
||||
|
|
@ -477,8 +555,20 @@ zupt_error_t zupt_compress_files(const char *out, const char **arc, const char *
|
|||
zupt_error_t zupt_extract_archive(const char *arc, const char *dir, zupt_options_t *opts);
|
||||
zupt_error_t zupt_list_archive(const char *arc, zupt_options_t *opts);
|
||||
zupt_error_t zupt_test_archive(const char *arc, zupt_options_t *opts);
|
||||
/* Internal stream variant used when a caller has pinned a private snapshot.
|
||||
* It never closes stream; the caller retains ownership. */
|
||||
zupt_error_t zupt_test_archive_stream(FILE *stream, zupt_options_t *opts);
|
||||
zupt_error_t zupt_open_archive_internal(FILE *stream, zupt_options_t *opts,
|
||||
zupt_archive_header_t *header,
|
||||
zupt_footer_t *footer,
|
||||
zupt_index_entry_t **entries,
|
||||
int *num_entries);
|
||||
|
||||
/* ─── Hybrid PQ KEM (ML-KEM-768 + X25519) ─── */
|
||||
/* Internal no-replace writer shared by the native and optional pq-box key
|
||||
* formats. Private material receives platform-specific restrictive access. */
|
||||
int zupt_keyfile_write_new(const char *path, const uint8_t *data, size_t length,
|
||||
int private_material);
|
||||
int zupt_hybrid_keygen(const char *keyfile);
|
||||
int zupt_hybrid_export_pubkey(const char *privfile, const char *pubfile);
|
||||
int zupt_hybrid_encrypt_init(zupt_keyring_t *kr, const char *pubkeyfile,
|
||||
|
|
@ -494,14 +584,14 @@ int zupt_pq_encrypt_init(zupt_keyring_t *kr, const char *pubkeyfile,
|
|||
int zupt_pq_decrypt_init(zupt_keyring_t *kr, const char *privkeyfile,
|
||||
const uint8_t *enc_hdr, size_t enc_hdr_len);
|
||||
|
||||
/* ─── SDK-backed crypto (zupt v2.2+, libzuptsdk under the hood) ─── */
|
||||
/* ─── SDK-backed crypto (zupt v2.2+, optional libvuptsdk) ─── */
|
||||
int zupt_sdk_hybrid_keygen(const char *privkeyfile, const char *pubkeyfile);
|
||||
int zupt_sdk_hybrid_encrypt_init(zupt_keyring_t *kr, const char *pubkeyfile,
|
||||
uint8_t *enc_hdr, size_t *enc_hdr_len);
|
||||
int zupt_sdk_hybrid_decrypt_init(zupt_keyring_t *kr, const char *privkeyfile,
|
||||
const uint8_t *enc_hdr, size_t enc_hdr_len);
|
||||
|
||||
/* pq-box mode (ZUPT_ENC_PQ_BOX_V1, vendored libpqvaptvupt) */
|
||||
/* pq-box mode (ZUPT_ENC_PQ_BOX_V1, optional system libpqvaptvupt) */
|
||||
int zupt_pqbox_keygen(const char *privkeyfile, const char *pubkeyfile);
|
||||
int zupt_pqbox_encrypt_init(zupt_keyring_t *kr, const char *pubkeyfile,
|
||||
uint8_t *enc_hdr, size_t *enc_hdr_len);
|
||||
|
|
@ -519,7 +609,7 @@ void zupt_format_size(uint64_t bytes, char *buf, size_t cap);
|
|||
|
||||
/* Resolve ZUPT_CODEC_AUTO to a concrete codec based on hardware.
|
||||
* On x86_64 with AVX2: VaptVupt (fast ANS+SIMD decode).
|
||||
* On all other arches: Zupt-LZHP (no SIMD dependency).
|
||||
* On all other arches: ZUPT-LZHP (no SIMD dependency).
|
||||
* Decompression of ALL codecs works on ALL architectures. */
|
||||
uint16_t zupt_resolve_auto_codec(void);
|
||||
|
||||
|
|
@ -538,18 +628,58 @@ zupt_error_t zupt_disk_restore(const char *archive_path, const char *target_path
|
|||
zupt_options_t *opts);
|
||||
|
||||
/* ─── Internal Block I/O (used by format + disk modules) ─── */
|
||||
typedef struct zupt_atomic_output zupt_atomic_output_t;
|
||||
|
||||
/* Create an archive in a private file next to OUTPUT_PATH. finish(..., 1)
|
||||
* atomically replaces only the final directory entry; it never follows a
|
||||
* symlink/reparse point at the leaf. finish(..., 0) removes the temporary. */
|
||||
zupt_atomic_output_t *zupt_atomic_output_open(const char *output_path,
|
||||
FILE **stream_out);
|
||||
int zupt_atomic_output_finish(zupt_atomic_output_t *output, int publish);
|
||||
|
||||
zupt_error_t read_block(FILE *f, zupt_block_t *b);
|
||||
zupt_error_t read_enc_header(FILE *f, zupt_archive_header_t *hdr, zupt_options_t *opts);
|
||||
zupt_error_t decompress_block(const zupt_block_t *b, const zupt_keyring_t *kr,
|
||||
uint64_t block_seq, uint8_t **out, size_t *olen);
|
||||
|
||||
/* Published 5.2.1 encrypted+dedup disk images bound DATA authentication to
|
||||
* each frame's linear sequence, while legacy references stored only offsets.
|
||||
* Readers build this private offset-to-sequence map before restoring them. */
|
||||
typedef struct {
|
||||
uint64_t offset;
|
||||
uint64_t aad_seq;
|
||||
} zupt_legacy_disk_aad_entry_t;
|
||||
|
||||
typedef struct {
|
||||
zupt_legacy_disk_aad_entry_t *entries;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
} zupt_legacy_disk_aad_map_t;
|
||||
|
||||
zupt_error_t zupt_legacy_disk_aad_map_build(
|
||||
FILE *stream, uint64_t first_block_offset, uint32_t block_count,
|
||||
zupt_legacy_disk_aad_map_t *map);
|
||||
int zupt_legacy_disk_aad_map_lookup(
|
||||
const zupt_legacy_disk_aad_map_t *map, uint64_t offset,
|
||||
uint64_t *aad_seq);
|
||||
void zupt_legacy_disk_aad_map_free(zupt_legacy_disk_aad_map_t *map);
|
||||
|
||||
zupt_error_t write_enc_header(FILE *out, zupt_archive_header_t *hdr,
|
||||
zupt_options_t *opts);
|
||||
int zupt_w8(FILE *f, uint8_t v);
|
||||
int zupt_w16le(FILE *f, uint16_t v);
|
||||
int zupt_w64le(FILE *f, uint64_t v);
|
||||
void zupt_serialize_archive_header(const zupt_archive_header_t *header,
|
||||
uint8_t out[ZUPT_ARCHIVE_HEADER_SIZE]);
|
||||
void zupt_serialize_footer(const zupt_footer_t *footer,
|
||||
uint8_t out[ZUPT_FOOTER_SIZE]);
|
||||
int zupt_write_archive_header(FILE *stream,
|
||||
const zupt_archive_header_t *header);
|
||||
int zupt_write_footer(FILE *stream, const zupt_footer_t *footer);
|
||||
|
||||
/* ─── Block-Level Deduplication ─── */
|
||||
#define ZUPT_DEDUP_MAX_ENTRIES (2 * 1024 * 1024) /* 2M entries, ~48MB RAM */
|
||||
#define ZUPT_DEDUP_MAX_ENTRIES (2 * 1024 * 1024) /* 2M entries, ~80MB RAM */
|
||||
#define ZUPT_DEDUP_DIGEST_SIZE 16 /* SHA-256 prefix paired with XXH64 */
|
||||
|
||||
typedef struct zupt_dedup_ctx zupt_dedup_ctx_t;
|
||||
|
||||
|
|
@ -566,6 +696,17 @@ void zupt_dedup_stats(const zupt_dedup_ctx_t *ctx,
|
|||
uint64_t *bytes_saved);
|
||||
int zupt_dedup_write_ref(FILE *out, uint64_t ref_offset,
|
||||
uint32_t orig_size, uint64_t orig_checksum);
|
||||
int zupt_dedup_write_ref_secure(FILE *out, uint64_t ref_offset,
|
||||
uint32_t orig_size, uint64_t orig_checksum,
|
||||
uint64_t current_aad_seq,
|
||||
uint64_t referenced_aad_seq,
|
||||
const zupt_keyring_t *keyring);
|
||||
zupt_error_t zupt_dedup_read_ref(const zupt_block_t *block,
|
||||
const zupt_keyring_t *keyring,
|
||||
int require_authentication,
|
||||
uint64_t current_aad_seq,
|
||||
uint64_t *ref_offset,
|
||||
uint64_t *referenced_aad_seq);
|
||||
|
||||
/* ─── Archive Info (read-only metadata inspection) ─── */
|
||||
zupt_error_t zupt_archive_info(const char *path);
|
||||
|
|
|
|||
Loading…
Reference in a new issue