Danube read-only SDK
The free edition of the library for reading .adn containers: a C
surface, a shared module and one header. The module only reads — there are no writing calls in
it — so it can be embedded in any product, commercial ones included.
version 3.3.0 The delivery is an
.adn container, unpacked with dan -method EXTRACT. Inside sits this
same guide as HTML: SDK.html (Russian) and SDK.en.html (English).
Unpack, link, read
Pick the delivery by system and loader; the module carries the compression engines inside, so no extra dependencies are needed. The password is passed on open; an empty string for an unencrypted container.
A container encrypted with a public key (release 3.3.0) is opened by the reader on its own:
it walks the default keys folder (~/.dan/keys, in Windows
%APPDATA%\danube\keys) and compares fingerprints with the recipient block. The facade
cannot set another folder or a private-key password yet — unlock the key beforehand or put an
unprotected copy next to it. Without a matching key danube_ro_open returns
DANUBE_RO_BAD_PASS, and the reason stays in the log.
Linux and macOS
dan -method EXTRACT -danube danube-ro-3.3.0_Linux_glibc_amd64.adn -dest . cc -Iinclude example.c -Llib -ldanube_ro -o example LD_LIBRARY_PATH=$PWD/lib ./example photos.adn # macOS: DYLD_LIBRARY_PATH
Windows
:: unpack the container dan -method EXTRACT -danube danube-ro-3.3.0_Windows_x86_64_mingw.adn -dest . :: MinGW-w64 gcc -Iinclude example.c -Llib -ldanube_ro -o example.exe :: MSVC, from a developer command prompt cl /Iinclude example.c lib\danube_ro.lib
Container details and a tree walk
#include <stdio.h> #include <danube_read.h> int main(int argc, char ** argv){ danube_ro_t * session = NULL; danube_ro_info_t info; danube_ro_node_t nodes[64]; uint64_t filled = 0, i; if(argc < 2) return 2; /* Open the container: close the session on any result code */ danube_ro_error_t code = danube_ro_open(argv[1], "", "", &session); if(code != DANUBE_RO_OK){ char message[DANUBE_RO_TEXT] = {0}; danube_ro_message(session, message, sizeof(message)); fprintf(stderr, "open: %d (%s)\n", (int) code, message); danube_ro_close(session); return 1; } /* Container details: format, nodes, bytes, parts */ danube_ro_info(session, &info); printf("format=%s nodes=%llu bytes=%llu parts=%llu\n", info.format, (unsigned long long) info.nodes, (unsigned long long) info.bytes, (unsigned long long) info.parts); /* Children of the root */ danube_ro_children(session, 0, 0, nodes, 64, &filled); for(i = 0; i < filled; i++) printf("%llu\t%s\t%llu\n", (unsigned long long) nodes[i].id, nodes[i].name, (unsigned long long) nodes[i].size); danube_ro_close(session); return 0; }
Everything below builds on this session: reading bytes, extraction, search and the keys store.
Bytes into memory and files to disk
Reading with seeking
danube_ro_node_t node; char buffer[65536]; size_t got = 0; danube_ro_node(session, 0, 0, "readme.txt", &node); /* The first 64 KiB and a chunk from offset 1 MiB */ danube_ro_read(session, node.id, 0, sizeof(buffer), buffer, sizeof(buffer), &got); danube_ro_read(session, node.id, 1024 * 1024, 0, buffer, sizeof(buffer), &got);
Only the frame the request touches is unpacked, so the call suits a viewer. A range past the end is not a refusal: success with nothing read.
Extraction to disk
/* The whole container, then one node or a list */ danube_ro_extract(session, "./out", NULL, 0); uint64_t ids[2] = {3, 7}; danube_ro_extract(session, "./out", ids, 2);
A vault container refuses extraction (DANUBE_RO_VAULT): its data is read into
memory only. Progress is attached with danube_ro_on_progress.
Seventeen surface calls
| Call | What it does |
|---|---|
| danube_ro_open | open a container; a session is created on any outcome but an empty path |
| danube_ro_close | close the session; the pointer is invalid afterwards |
| danube_ro_message | explanation of the last refusal |
| danube_ro_info | details: flags, nodes, bytes, parts, dates, author |
| danube_ro_version | version of the built module |
| danube_ro_count | number of children of a folder |
| danube_ro_children | list children page by page |
| danube_ro_node | details of a node by id or by name inside a folder |
| danube_ro_path | full path of a node inside the container |
| danube_ro_search | search by name, exact or partial |
| danube_ro_read | read data into memory with seeking |
| danube_ro_extract | extract the whole container, one node or a list |
| danube_ro_check | integrity check, verified data in percent |
| danube_ro_keys | list the keys of the store |
| danube_ro_keys_export | write the keys as files into a folder |
| danube_ro_show | show key values in later calls of the session |
| danube_ro_on_progress | attach or detach the progress handler |
What a refusal means
| Code | Meaning |
|---|---|
| DANUBE_RO_OK (0) | success |
| DANUBE_RO_ERROR (1) | refusal, details in danube_ro_message |
| DANUBE_RO_NO_FILE (2) | no container at the address |
| DANUBE_RO_BAD_PASS (3) | wrong password |
| DANUBE_RO_FORMAT (4) | the format cannot be parsed; this edition needs 4.0.0 |
| DANUBE_RO_VAULT (5) | vault: extraction to disk is refused |
| DANUBE_RO_DENIED (6) | the action is not allowed |
| DANUBE_RO_NOT_FOUND (7) | there is no such node or keys store |
| DANUBE_RO_IO (8) | filesystem error |
| DANUBE_RO_SMALL (9) | buffer too small, the value is clipped and zero terminated |
| DANUBE_RO_STOP (10) | stopped by the caller |
Fixed size fields of the structures are clipped silently — DANUBE_RO_SMALL
never appears for them. A session is not thread safe: one thread, one session.
Container 4.0.0 and its parts
4.0.0 containers are read; archives of previous releases are refused with
DANUBE_RO_FORMAT. A split container is the main .adn file plus
.pdn parts; a part is identified by its header (archive identifier and part number), so
it may be renamed, while a part of another archive in the same folder is neither used nor damaged.
The number of parts comes from danube_ro_info, the number of pieces inside a node from
danube_ro_node.
Inside the container: lib/ — the module, include/danube_read.h — the
surface, LICENSE — version 1.1 with section 3.4, THIRD-PARTY-LICENSES.md,
README-SDK.txt — a note about the build leg, SDK.html and
SDK.en.html — this guide.
Why a container and not an archive: dan is already installed at this point — otherwise
there would be no reason to download the SDK. It also demonstrates the format itself: the delivery can
be opened with INFO, checked with DIAGNOSTIC and unpacked with the stock extraction.
Distribution terms: the edition is free for any use, commercial included; embedding,
linking of any kind, redistribution of unmodified copies and building the danube_ro
target from source are allowed. The writing part of the library is licensed commercially
(section 3.1).
SDK builds
Seventeen containers for Windows, macOS, Linux, BSD, Solaris and illumos, x86_64 and ARM64.
dan -method EXTRACT -danube danube-ro-3.3.0_Linux_glibc_amd64.adn -dest .
| System | Build | Architecture | Files |
|---|---|---|---|
| Windowsyour system | MinGW-w64 (GCC) | x86_64 | adn |
| MinGW-w64 (clang) | ARM64 | adn | |
| MSVC | x86_64 | adn | |
| ARM64 | adn | ||
| macOSyour system | Apple Silicon | adn | |
| Linuxyour system | glibc | AMD64 | adn |
| ARM64 | adn | ||
| musl | AMD64 | adn | |
| FreeBSDyour system | AMD64 | adn | |
| ARM64 | adn | ||
| NetBSDyour system | AMD64 | adn | |
| ARM64 | adn | ||
| OpenBSDyour system | AMD64 | adn | |
| ARM64 | adn | ||
| DragonFly BSDyour system | AMD64 | adn | |
| Solarisyour system | Solaris 11.4 | AMD64 | adn |
| OpenIndiana (illumos) | AMD64 | adn |