As a starting point in the task of trying to understand the pristine database format, create a subcommand - pristine - that can be used to dump various bits of information from a repository .pijul/pristine/db file.
For now, the subcommand parses out the globalheader in each root page, and prints the information there. We have learned that Pijul uses a fixed number of root pages (2), but Sanakirja supports a user-provided number of roots.
ZYBYX2TBKWAKNMPCWT3B7CJRDEO3LOENGOXZF27JGD4UH6YCN25AC SMB3M6ESOIR2LMFII2VFQJSPFIUYXHD7CXYARIGOKPB2QF2ORFLAC YM2LC6QP2D7TK3JUKOXWUWTQEGMCEGQDGPTOZPWC3BRDFNRKSZWQC XJ2PEH74CLJUELZBR47QHGUSKXB4Z5T7EKEF6Y4CYY2VBHZXUTDAC 67HZZ5HS7AA5KA6W4TV24YMO33V5FR6GJ34P3FPTRN547RFNL4DQC PEUS54XQ5KJQYAVUYBG5MWLEHIOVPMZ3ANVC7HPQP6JUWWPRDW5AC ZTDGWUGPKDVIUA6V5BZ5ATDTGKZEE6ZZIXLGNTUJU2KIV7H7YSVQC DRK7G22JO77N3RP5SS4ICZODMLYHJONKNPXREODMFC6YZVDHUXBQC FB67XX5EGNF45JNAQISW7CBLSLS36F6JEUOBTTPUMVBMOVLGA3VQC B3XLVPNC4COLLC3FUE34Y7HIKTMF6CJZUASZOU3YM2YGPZKJZP7QC XTKRT6OQYN4LARQRDLI2KBSAJTOFZNT4AMBZ46CPUDZXD7IDYYWQC ZPNA2D42RFGGC45PLDYDGQUDPC7D4NBEH2HD4Y2L5P2CK3R52FAQC #ifndef ANI_DB_H#define ANI_DB_Hstruct globalheader {u16 version; // sanakirja versionu8 root; // which page is currently the root page?u8 nroots; // how many root pages are there?u32 crc; // CRC of this pageu64 length; // first free page at the end of the fileu64 freedb; // offset of the free listu64 rcdb; // offset of the RC db};void dbrun(char *);#endif
#include <stdint.h>#include <stddef.h>#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <unistd.h>#include <stdbool.h>#include <sys/mman.h>#include "common.h"#include "types.h"#include "scaffold.h"#include "db.h"#define err(msg) \do { \perror(msg); \exit(EXIT_FAILURE); \} while (0)static voiddumpbytes(u8 *mem, usize len){usize i;for (i = 0; i < len; i++) {printf("%02x ", mem[i]);}printf("\n");}static voidreadglobalheader(u8 *mem, struct globalheader *gh){dumpbytes(mem, sizeof(struct globalheader));// FIXME: Does not work for big-endian systems*gh = *((struct globalheader *)mem);}static voidprintglobalheader(struct globalheader *gh, bool currentroot){printf("version = %u root = %u %s nroots = %u\n", gh->version, gh->root,currentroot ? "(current)" : "", gh->nroots);printf("CRC = 0x%04x (%u)\n", gh->crc, gh->crc);printf("length = %lu (0x%08lx)\n", gh->length, gh->length);printf("freedb = %lu\n", gh->freedb);printf("rcdb = %lu\n", gh->rcdb);}voiddbrun(char *db){int fd;u8 *addr;u8 nroots, curroot;size i;struct globalheader gh;printf("opening %s\n", db);fd = open(db, O_RDONLY);if (fd == -1)err("open");usize length = 4096;int prot = PROT_READ; // memory protection; PROT_{EXEC,READ,WRITE,NONE}int flags = MAP_PRIVATE; // determines visibilityoff_t offset = 0;addr = mmap(NULL, length, prot, flags, fd, offset);if (addr == MAP_FAILED)err("mmap");readglobalheader(addr, &gh);munmap(addr, length);nroots = gh.nroots;curroot = gh.root;printglobalheader(&gh, curroot == 0);// for nroots-1 times, read the i << 12'th pagefor (i = 1; i < nroots; i++) {addr = mmap(NULL, length, prot, flags, fd, i << 12);if (addr == MAP_FAILED)err("mmap2");readglobalheader(addr, &gh);munmap(addr, length);printglobalheader(&gh, curroot == i);}close(fd);}
#include <stdint.h>#include <stddef.h>#include <unistd.h>#include <string.h>#include "common.h"#include "types.h"#include "repository.h"#include "db.h"static voidformatdbpath(char *dst, const char *repodir){char *p;p = stpncpy(dst, repodir, PATH_MAX);*p++ = '/';p = stpncpy(p, DOTPIJUL, 6);*p++ = '/';p = stpncpy(p, "pristine/db", 11);}intcmd_pristine(int argc, char *argv, struct repository *repo){char dbpath[4096] = { 0 };(void)argc;(void)argv;formatdbpath(dbpath, repo->path);dbrun(dbpath);return 0;}
" init Initialize empty repository\n"" change Show information about a particular change\n";
" init Initialize empty repository\n"" change Show information about a particular change\n"" pristine Show information about the repository database\n";