iRefactor dedup into multiple programs - dedup - deduplicating backup program Err bitreich.org 70 hgit clone git://bitreich.org/dedup/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/dedup/ URL:git://bitreich.org/dedup/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/dedup/ bitreich.org 70 1Log /scm/dedup/log.gph bitreich.org 70 1Files /scm/dedup/files.gph bitreich.org 70 1Refs /scm/dedup/refs.gph bitreich.org 70 1Tags /scm/dedup/tag bitreich.org 70 1README /scm/dedup/file/README.gph bitreich.org 70 1LICENSE /scm/dedup/file/LICENSE.gph bitreich.org 70 i--- Err bitreich.org 70 1commit 1dbc2650dde7d194f7b87e51abc5efeab4b61eb0 /scm/dedup/commit/1dbc2650dde7d194f7b87e51abc5efeab4b61eb0.gph bitreich.org 70 1parent 6c3de1be215d063566c45bb412301088abf18add /scm/dedup/commit/6c3de1be215d063566c45bb412301088abf18add.gph bitreich.org 70 hAuthor: sin URL:mailto:sin@2f30.org bitreich.org 70 iDate: Wed, 17 Apr 2019 16:49:05 +0100 Err bitreich.org 70 i Err bitreich.org 70 iRefactor dedup into multiple programs Err bitreich.org 70 i Err bitreich.org 70 idinit(1) - Initialize a repository Err bitreich.org 70 idlist(1) - List snapshots Err bitreich.org 70 idinfo(1) - Print information about the repository Err bitreich.org 70 idpack(1) - Create snapshot from stdin Err bitreich.org 70 idunpack(1) - Extract snapshot to stdout Err bitreich.org 70 idcheck(1) - Check if repository is consistent Err bitreich.org 70 i Err bitreich.org 70 iNeeds more work to share the code properly. Err bitreich.org 70 i Err bitreich.org 70 iDiffstat: Err bitreich.org 70 i M Makefile | 61 ++++++++++++++++++++++++------- Err bitreich.org 70 i M README | 19 ++++++++++--------- Err bitreich.org 70 i A dcheck.1 | 25 +++++++++++++++++++++++++ Err bitreich.org 70 i A dcheck.c | 316 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i D dedup.1 | 62 ------------------------------- Err bitreich.org 70 i D dedup.c | 700 ------------------------------- Err bitreich.org 70 i A dinfo.1 | 25 +++++++++++++++++++++++++ Err bitreich.org 70 i A dinfo.c | 170 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i A dinit.1 | 39 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i A dinit.c | 155 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i A dlist.1 | 25 +++++++++++++++++++++++++ Err bitreich.org 70 i A dlist.c | 232 ++++++++++++++++++++++++++++++ Err bitreich.org 70 i A dpack.1 | 35 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i A dpack.c | 422 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i A dunpack.1 | 28 ++++++++++++++++++++++++++++ Err bitreich.org 70 i A dunpack.c | 288 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i Err bitreich.org 70 i16 files changed, 1818 insertions(+), 784 deletions(-) Err bitreich.org 70 i--- Err bitreich.org 70 1diff --git a/Makefile b/Makefile /scm/dedup/file/Makefile.gph bitreich.org 70 i@@ -3,7 +3,16 @@ include config.mk Err bitreich.org 70 i VERSION = 1.0 Err bitreich.org 70 i PREFIX = /usr/local Err bitreich.org 70 i MANPREFIX = $(PREFIX)/man Err bitreich.org 70 i-TARGET = dedup Err bitreich.org 70 i+TARGET = dcheck dinfo dinit dlist dpack dunpack Err bitreich.org 70 i+ Err bitreich.org 70 i+MAN = \ Err bitreich.org 70 i+ dcheck.1 \ Err bitreich.org 70 i+ dinfo.1 \ Err bitreich.org 70 i+ dinit.1 \ Err bitreich.org 70 i+ dlist.1 \ Err bitreich.org 70 i+ dpack.1 \ Err bitreich.org 70 i+ dunpack.1 \ Err bitreich.org 70 i+ Err bitreich.org 70 i HDR = \ Err bitreich.org 70 i arg.h \ Err bitreich.org 70 i blake2-impl.h \ Err bitreich.org 70 i@@ -23,7 +32,12 @@ SRC = \ Err bitreich.org 70 i compress-none.c \ Err bitreich.org 70 i compress-snappy.c \ Err bitreich.org 70 i compress.c \ Err bitreich.org 70 i- dedup.c \ Err bitreich.org 70 i+ dcheck.c \ Err bitreich.org 70 i+ dinfo.c \ Err bitreich.org 70 i+ dinit.c \ Err bitreich.org 70 i+ dlist.c \ Err bitreich.org 70 i+ dpack.c \ Err bitreich.org 70 i+ dunpack.c \ Err bitreich.org 70 i hash-blake2b.c \ Err bitreich.org 70 i hash-blake2bp.c \ Err bitreich.org 70 i hash-blake2s.c \ Err bitreich.org 70 i@@ -35,7 +49,7 @@ SRC = \ Err bitreich.org 70 i unpack.c \ Err bitreich.org 70 i utils.c \ Err bitreich.org 70 i Err bitreich.org 70 i-OBJ = \ Err bitreich.org 70 i+COMMOBJ = \ Err bitreich.org 70 i blake2b-ref.o \ Err bitreich.org 70 i blake2bp-ref.o \ Err bitreich.org 70 i blake2s-ref.o \ Err bitreich.org 70 i@@ -45,7 +59,6 @@ OBJ = \ Err bitreich.org 70 i compress-none.o \ Err bitreich.org 70 i compress-snappy.o \ Err bitreich.org 70 i compress.o \ Err bitreich.org 70 i- dedup.o \ Err bitreich.org 70 i hash-blake2b.o \ Err bitreich.org 70 i hash-blake2bp.o \ Err bitreich.org 70 i hash-blake2s.o \ Err bitreich.org 70 i@@ -57,14 +70,21 @@ OBJ = \ Err bitreich.org 70 i unpack.o \ Err bitreich.org 70 i utils.o \ Err bitreich.org 70 i Err bitreich.org 70 i+DCHECKOBJ = $(COMMOBJ) dcheck.o Err bitreich.org 70 i+DINFOOBJ = $(COMMOBJ) dinfo.o Err bitreich.org 70 i+DINITOBJ = $(COMMOBJ) dinit.o Err bitreich.org 70 i+DLISTOBJ = $(COMMOBJ) dlist.o Err bitreich.org 70 i+DPACKOBJ = $(COMMOBJ) dpack.o Err bitreich.org 70 i+DUNPACKOBJ = $(COMMOBJ) dunpack.o Err bitreich.org 70 i+ Err bitreich.org 70 i DISTFILES = \ Err bitreich.org 70 i+ $(MAN) \ Err bitreich.org 70 i $(SRC) \ Err bitreich.org 70 i CHANGELOG \ Err bitreich.org 70 i LICENSE \ Err bitreich.org 70 i Makefile \ Err bitreich.org 70 i README \ Err bitreich.org 70 i config.mk \ Err bitreich.org 70 i- dedup.1 \ Err bitreich.org 70 i Err bitreich.org 70 i CFLAGS = -g -O2 -Wall $(OPENMPCFLAGS) Err bitreich.org 70 i CPPFLAGS = -I/usr/local/include -D_FILE_OFFSET_BITS=64 Err bitreich.org 70 i@@ -73,20 +93,20 @@ LDLIBS = -llz4 -lsnappy $(OPENMPLDLIBS) Err bitreich.org 70 i Err bitreich.org 70 i all: $(TARGET) Err bitreich.org 70 i Err bitreich.org 70 i-$(OBJ): $(HDR) Err bitreich.org 70 i+$(DCHECKOBJ) $(DINFOOBJ) $(DINITOBJ) $(DLISTOBJ) $(DPACKOBJ) $(DUNPACKOBJ): $(HDR) Err bitreich.org 70 i Err bitreich.org 70 i clean: Err bitreich.org 70 i- rm -f $(OBJ) dedup dedup-$(VERSION).tar.gz Err bitreich.org 70 i+ rm -f $(DCHECKOBJ) $(DINFOOBJ) $(DINITOBJ) $(DLISTOBJ) $(DPACKOBJ) $(DUNPACKOBJ) $(TARGET) dedup-$(VERSION).tar.gz Err bitreich.org 70 i Err bitreich.org 70 i install: all Err bitreich.org 70 i mkdir -p $(DESTDIR)$(PREFIX)/bin Err bitreich.org 70 i- cp -f dedup $(DESTDIR)$(PREFIX)/bin Err bitreich.org 70 i+ cp -f $(TARGET) $(DESTDIR)$(PREFIX)/bin Err bitreich.org 70 i mkdir -p $(DESTDIR)$(MANPREFIX)/man1 Err bitreich.org 70 i- cp -f dedup.1 $(DESTDIR)$(MANPREFIX)/man1 Err bitreich.org 70 i+ cp -f $(MAN) $(DESTDIR)$(MANPREFIX)/man1 Err bitreich.org 70 i Err bitreich.org 70 i uninstall: Err bitreich.org 70 i- rm -f $(DESTDIR)$(PREFIX)/bin/dedup Err bitreich.org 70 i- rm -f $(DESTDIR)$(MANPREFIX)/man1/dedup.1 Err bitreich.org 70 i+ cd $(DESTDIR)$(PREFIX)/bin && rm -f $(TARGET) Err bitreich.org 70 i+ cd $(DESTDIR)$(MANPREFIX)/man1 && rm -f $(MAN) Err bitreich.org 70 i Err bitreich.org 70 i dist: Err bitreich.org 70 i mkdir -p dedup-$(VERSION) Err bitreich.org 70 i@@ -102,5 +122,20 @@ dist: Err bitreich.org 70 i .c.o: Err bitreich.org 70 i $(CC) $(CPPFLAGS) $(CFLAGS) -c $< Err bitreich.org 70 i Err bitreich.org 70 i-dedup: $(OBJ) Err bitreich.org 70 i- $(CC) -o $@ $(OBJ) $(LDFLAGS) $(LDLIBS) Err bitreich.org 70 i+dcheck: $(DCHECKOBJ) Err bitreich.org 70 i+ $(CC) -o $@ $(DCHECKOBJ) $(LDFLAGS) $(LDLIBS) Err bitreich.org 70 i+ Err bitreich.org 70 i+dinfo: $(DINFOOBJ) Err bitreich.org 70 i+ $(CC) -o $@ $(DINFOOBJ) $(LDFLAGS) $(LDLIBS) Err bitreich.org 70 i+ Err bitreich.org 70 i+dinit: $(DINITOBJ) Err bitreich.org 70 i+ $(CC) -o $@ $(DINITOBJ) $(LDFLAGS) $(LDLIBS) Err bitreich.org 70 i+ Err bitreich.org 70 i+dlist: $(DLISTOBJ) Err bitreich.org 70 i+ $(CC) -o $@ $(DLISTOBJ) $(LDFLAGS) $(LDLIBS) Err bitreich.org 70 i+ Err bitreich.org 70 i+dpack: $(DPACKOBJ) Err bitreich.org 70 i+ $(CC) -o $@ $(DPACKOBJ) $(LDFLAGS) $(LDLIBS) Err bitreich.org 70 i+ Err bitreich.org 70 i+dunpack: $(DUNPACKOBJ) Err bitreich.org 70 i+ $(CC) -o $@ $(DUNPACKOBJ) $(LDFLAGS) $(LDLIBS) Err bitreich.org 70 1diff --git a/README b/README /scm/dedup/file/README.gph bitreich.org 70 i@@ -8,29 +8,30 @@ Getting started Err bitreich.org 70 i Err bitreich.org 70 i To use dedup you have to first initialize the repository. Err bitreich.org 70 i Err bitreich.org 70 i- dedup -r ~/repo -i Err bitreich.org 70 i+ dinit repo Err bitreich.org 70 i+ Err bitreich.org 70 i+This will create .{snapshots,store} files in the repo directory. The Err bitreich.org 70 i+store file contains all the unique blocks. The snapshots file Err bitreich.org 70 i+contains all the revisions of files that have been deduplicated. Err bitreich.org 70 i Err bitreich.org 70 i dedup only handles a single file at a time, so using tar is advised. Err bitreich.org 70 i-For example, to dedup a directory tree you can invoke dedup as Err bitreich.org 70 i+For example, to dedup a directory tree you can invoke dpack as Err bitreich.org 70 i follows: Err bitreich.org 70 i Err bitreich.org 70 i- tar -c ~/dir | dedup -r ~/repo -m "$(date)" Err bitreich.org 70 i+ tar -c ~/dir | dpack -m "$(date)" repo Err bitreich.org 70 i Err bitreich.org 70 i-This will create .{snapshots,store} files in the ~/repo directory. Err bitreich.org 70 i-The store file contains all the unique blocks. The snapshots file Err bitreich.org 70 i-contains all the revisions of files that have been deduplicated. The Err bitreich.org 70 i--m flag is used to attach an arbitrary message to the snapshot. Err bitreich.org 70 i+The -m flag is used to attach an arbitrary message to the snapshot. Err bitreich.org 70 i Err bitreich.org 70 i To list all known revisions run: Err bitreich.org 70 i Err bitreich.org 70 i- dedup -r ~/repo -l Err bitreich.org 70 i+ dlist repo Err bitreich.org 70 i Err bitreich.org 70 i You will get a list of hashes. Each hash corresponds to a single file Err bitreich.org 70 i (in this case, a tar archive). Err bitreich.org 70 i Err bitreich.org 70 i To extract a file from the deduplicated store run: Err bitreich.org 70 i Err bitreich.org 70 i- dedup -r ~/repo -e > dir.tar Err bitreich.org 70 i+ dunpack -e repo > snapshot.tar Err bitreich.org 70 i Err bitreich.org 70 i Portability Err bitreich.org 70 i =========== Err bitreich.org 70 1diff --git a/dcheck.1 b/dcheck.1 /scm/dedup/file/dcheck.1.gph bitreich.org 70 i@@ -0,0 +1,25 @@ Err bitreich.org 70 i+.Dd April 17, 2019 Err bitreich.org 70 i+.Dt DCHECK 1 Err bitreich.org 70 i+.Os Err bitreich.org 70 i+.Sh NAME Err bitreich.org 70 i+.Nm dcheck Err bitreich.org 70 i+.Nd Perform consistency checks on a dedup repo Err bitreich.org 70 i+.Sh SYNOPSIS Err bitreich.org 70 i+.Nm dcheck Err bitreich.org 70 i+.Op Fl v Err bitreich.org 70 i+.Op repo Err bitreich.org 70 i+.Sh DESCRIPTION Err bitreich.org 70 i+.Nm Err bitreich.org 70 i+performs consistency checks on a dedup repo. Err bitreich.org 70 i+If no Err bitreich.org 70 i+.Ar repo Err bitreich.org 70 i+is specified, then the current directory Err bitreich.org 70 i+is assumed to be the repository. Err bitreich.org 70 i+.Sh OPTIONS Err bitreich.org 70 i+.Bl -tag -width "-v" Err bitreich.org 70 i+.It Fl v Err bitreich.org 70 i+Enable verbose mode. Err bitreich.org 70 i+.El Err bitreich.org 70 i+.Sh AUTHORS Err bitreich.org 70 i+.An Dimitris Papastamos Aq Mt sin@2f30.org , Err bitreich.org 70 i+.An z3bra Aq Mt contactatz3bradotorg . Err bitreich.org 70 1diff --git a/dcheck.c b/dcheck.c /scm/dedup/file/dcheck.c.gph bitreich.org 70 i@@ -0,0 +1,316 @@ Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+#include "arg.h" Err bitreich.org 70 i+#include "blake2.h" Err bitreich.org 70 i+#include "dedup.h" Err bitreich.org 70 i+ Err bitreich.org 70 i+#define SNAPSF ".snapshots" Err bitreich.org 70 i+#define STOREF ".store" Err bitreich.org 70 i+ Err bitreich.org 70 i+enum { Err bitreich.org 70 i+ WALK_CONTINUE, Err bitreich.org 70 i+ WALK_STOP Err bitreich.org 70 i+}; Err bitreich.org 70 i+ Err bitreich.org 70 i+static struct snap_hdr snap_hdr; Err bitreich.org 70 i+static struct blk_hdr blk_hdr; Err bitreich.org 70 i+static int ifd; Err bitreich.org 70 i+static int sfd; Err bitreich.org 70 i+static int hash_algo = HASH_BLAKE2B; Err bitreich.org 70 i+static int compr_algo = COMPR_LZ4; Err bitreich.org 70 i+ Err bitreich.org 70 i+int verbose; Err bitreich.org 70 i+char *argv0; Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+print_md(FILE *fp, uint8_t *md, size_t size) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ size_t i; Err bitreich.org 70 i+ Err bitreich.org 70 i+ for (i = 0; i < size; i++) Err bitreich.org 70 i+ fprintf(fp, "%02x", md[i]); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static struct snap * Err bitreich.org 70 i+alloc_snap(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct snap *snap; Err bitreich.org 70 i+ Err bitreich.org 70 i+ snap = calloc(1, sizeof(*snap)); Err bitreich.org 70 i+ if (snap == NULL) Err bitreich.org 70 i+ err(1, "%s", __func__); Err bitreich.org 70 i+ return snap; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+free_snap(struct snap *snap) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ free(snap); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static struct snap * Err bitreich.org 70 i+grow_snap(struct snap *snap, uint64_t nr_blk_descs) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ size_t size; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (nr_blk_descs > SIZE_MAX / sizeof(snap->blk_desc[0])) Err bitreich.org 70 i+ errx(1, "%s: overflow", __func__); Err bitreich.org 70 i+ size = nr_blk_descs * sizeof(snap->blk_desc[0]); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (size > SIZE_MAX - sizeof(*snap)) Err bitreich.org 70 i+ errx(1, "%s: overflow", __func__); Err bitreich.org 70 i+ size += sizeof(*snap); Err bitreich.org 70 i+ Err bitreich.org 70 i+ snap = realloc(snap, size); Err bitreich.org 70 i+ if (snap == NULL) Err bitreich.org 70 i+ err(1, "%s", __func__); Err bitreich.org 70 i+ return snap; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static uint8_t * Err bitreich.org 70 i+alloc_buf(size_t size) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ void *p; Err bitreich.org 70 i+ Err bitreich.org 70 i+ p = calloc(1, size); Err bitreich.org 70 i+ if (p == NULL) Err bitreich.org 70 i+ err(1, "%s", __func__); Err bitreich.org 70 i+ return p; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+free_buf(uint8_t *buf) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ free(buf); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+hash_blk(uint8_t *buf, size_t size, uint8_t *md) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct hash_ctx ctx; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (hash_init(&ctx, hash_algo, MD_SIZE) < 0) Err bitreich.org 70 i+ errx(1, "hash_init failed"); Err bitreich.org 70 i+ hash_update(&ctx, buf, size); Err bitreich.org 70 i+ hash_final(&ctx, md, MD_SIZE); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+read_blk(uint8_t *buf, struct blk_desc *blk_desc) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ ssize_t n; Err bitreich.org 70 i+ Err bitreich.org 70 i+ xlseek(sfd, blk_desc->offset, SEEK_SET); Err bitreich.org 70 i+ n = xread(sfd, buf, blk_desc->size); Err bitreich.org 70 i+ if (n == 0) Err bitreich.org 70 i+ errx(1, "%s: unexpected EOF", __func__); Err bitreich.org 70 i+ if (n != blk_desc->size) Err bitreich.org 70 i+ errx(1, "%s: short read", __func__); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+/* Err bitreich.org 70 i+ * Hash every block referenced by the given snapshot Err bitreich.org 70 i+ * and compare its hash with the one stored in the corresponding Err bitreich.org 70 i+ * block descriptor. Err bitreich.org 70 i+ */ Err bitreich.org 70 i+static int Err bitreich.org 70 i+check_snap(struct snap *snap, void *arg) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct compr_ctx ctx; Err bitreich.org 70 i+ uint8_t *buf; Err bitreich.org 70 i+ int *ret = arg; Err bitreich.org 70 i+ uint64_t i; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (verbose > 0) { Err bitreich.org 70 i+ fprintf(stderr, "Checking snapshot: "); Err bitreich.org 70 i+ print_md(stderr, snap->md, sizeof(snap->md)); Err bitreich.org 70 i+ fputc('\n', stderr); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (compr_init(&ctx, compr_algo) < 0) Err bitreich.org 70 i+ errx(1, "compr_init failed"); Err bitreich.org 70 i+ buf = alloc_buf(compr_size(&ctx, BLKSIZE_MAX)); Err bitreich.org 70 i+ for (i = 0; i < snap->nr_blk_descs; i++) { Err bitreich.org 70 i+ uint8_t md[MD_SIZE]; Err bitreich.org 70 i+ struct blk_desc *blk_desc; Err bitreich.org 70 i+ Err bitreich.org 70 i+ blk_desc = &snap->blk_desc[i]; Err bitreich.org 70 i+ read_blk(buf, blk_desc); Err bitreich.org 70 i+ hash_blk(buf, blk_desc->size, md); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (memcmp(blk_desc->md, md, sizeof(blk_desc->md)) == 0) Err bitreich.org 70 i+ continue; Err bitreich.org 70 i+ Err bitreich.org 70 i+ fprintf(stderr, "Block hash mismatch\n"); Err bitreich.org 70 i+ fprintf(stderr, " Expected hash: "); Err bitreich.org 70 i+ print_md(stderr, blk_desc->md, sizeof(blk_desc->md)); Err bitreich.org 70 i+ fputc('\n', stderr); Err bitreich.org 70 i+ fprintf(stderr, " Actual hash: "); Err bitreich.org 70 i+ print_md(stderr, md, sizeof(md)); Err bitreich.org 70 i+ fputc('\n', stderr); Err bitreich.org 70 i+ fprintf(stderr, " Offset: %llu\n", Err bitreich.org 70 i+ (unsigned long long)blk_desc->offset); Err bitreich.org 70 i+ fprintf(stderr, " Size: %llu\n", Err bitreich.org 70 i+ (unsigned long long)blk_desc->size); Err bitreich.org 70 i+ *ret = -1; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ free_buf(buf); Err bitreich.org 70 i+ compr_final(&ctx); Err bitreich.org 70 i+ return WALK_CONTINUE; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+/* Walk through all snapshots and call fn() on each one */ Err bitreich.org 70 i+static void Err bitreich.org 70 i+walk_snap(int (*fn)(struct snap *, void *), void *arg) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ uint64_t i; Err bitreich.org 70 i+ Err bitreich.org 70 i+ xlseek(ifd, SNAP_HDR_SIZE, SEEK_SET); Err bitreich.org 70 i+ for (i = 0; i < snap_hdr.nr_snaps; i++) { Err bitreich.org 70 i+ struct snap *snap; Err bitreich.org 70 i+ int ret; Err bitreich.org 70 i+ Err bitreich.org 70 i+ snap = alloc_snap(); Err bitreich.org 70 i+ read_snap(ifd, snap); Err bitreich.org 70 i+ snap = grow_snap(snap, snap->nr_blk_descs); Err bitreich.org 70 i+ read_snap_descs(ifd, snap); Err bitreich.org 70 i+ Err bitreich.org 70 i+ ret = (*fn)(snap, arg); Err bitreich.org 70 i+ free_snap(snap); Err bitreich.org 70 i+ if (ret == WALK_STOP) Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ } Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+match_ver(uint64_t v) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ uint8_t maj, min; Err bitreich.org 70 i+ Err bitreich.org 70 i+ min = v & VER_MIN_MASK; Err bitreich.org 70 i+ maj = (v >> VER_MAJ_SHIFT) & VER_MAJ_MASK; Err bitreich.org 70 i+ if (maj == VER_MAJ && min == VER_MIN) Err bitreich.org 70 i+ return; Err bitreich.org 70 i+ errx(1, "format version mismatch: expected %u.%u but got %u.%u", Err bitreich.org 70 i+ VER_MAJ, VER_MIN, maj, min); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+load_blk_hdr(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ uint64_t v; Err bitreich.org 70 i+ Err bitreich.org 70 i+ xlseek(sfd, 0, SEEK_SET); Err bitreich.org 70 i+ read_blk_hdr(sfd, &blk_hdr); Err bitreich.org 70 i+ match_ver(blk_hdr.flags); Err bitreich.org 70 i+ Err bitreich.org 70 i+ v = blk_hdr.flags >> COMPR_ALGO_SHIFT; Err bitreich.org 70 i+ v &= COMPR_ALGO_MASK; Err bitreich.org 70 i+ compr_algo = v; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (compr_algo < 0 || compr_algo >= NR_COMPRS) Err bitreich.org 70 i+ errx(1, "unsupported compression algorithm: %d", compr_algo); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (verbose > 0) Err bitreich.org 70 i+ fprintf(stderr, "Compression algorithm: %s\n", Err bitreich.org 70 i+ compr_type2name(compr_algo)); Err bitreich.org 70 i+ Err bitreich.org 70 i+ v = blk_hdr.flags >> HASH_ALGO_SHIFT; Err bitreich.org 70 i+ v &= HASH_ALGO_MASK; Err bitreich.org 70 i+ hash_algo = v; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (hash_algo < 0 || hash_algo >= NR_HASHES) Err bitreich.org 70 i+ errx(1, "unsupported hash algorithm: %d", hash_algo); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (verbose > 0) Err bitreich.org 70 i+ fprintf(stderr, "Hash algorithm: %s\n", Err bitreich.org 70 i+ hash_type2name(hash_algo)); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+load_snap_hdr(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ xlseek(ifd, 0, SEEK_SET); Err bitreich.org 70 i+ read_snap_hdr(ifd, &snap_hdr); Err bitreich.org 70 i+ match_ver(snap_hdr.flags); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+init(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ ifd = open(SNAPSF, O_RDONLY, 0600); Err bitreich.org 70 i+ if (ifd < 0) Err bitreich.org 70 i+ err(1, "open %s", SNAPSF); Err bitreich.org 70 i+ Err bitreich.org 70 i+ sfd = open(STOREF, O_RDONLY, 0600); Err bitreich.org 70 i+ if (sfd < 0) Err bitreich.org 70 i+ err(1, "open %s", STOREF); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (flock(ifd, LOCK_NB | LOCK_EX) < 0 || Err bitreich.org 70 i+ flock(sfd, LOCK_NB | LOCK_EX) < 0) Err bitreich.org 70 i+ err(1, "flock"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ load_snap_hdr(); Err bitreich.org 70 i+ load_blk_hdr(); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+term(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ close(sfd); Err bitreich.org 70 i+ close(ifd); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+usage(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ fprintf(stderr, "usage: %s [-v] [repo]\n", argv0); Err bitreich.org 70 i+ exit(1); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+main(int argc, char *argv[]) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ char *repo = NULL; Err bitreich.org 70 i+ int ret; Err bitreich.org 70 i+ Err bitreich.org 70 i+ ARGBEGIN { Err bitreich.org 70 i+ case 'v': Err bitreich.org 70 i+ verbose++; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ default: Err bitreich.org 70 i+ usage(); Err bitreich.org 70 i+ } ARGEND Err bitreich.org 70 i+ Err bitreich.org 70 i+ switch (argc) { Err bitreich.org 70 i+ case 0: Err bitreich.org 70 i+ repo = "."; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case 1: Err bitreich.org 70 i+ repo = argv[0]; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ default: Err bitreich.org 70 i+ usage(); Err bitreich.org 70 i+ }; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (chdir(repo) < 0) Err bitreich.org 70 i+ err(1, "chdir: %s", repo); Err bitreich.org 70 i+ Err bitreich.org 70 i+ init(); Err bitreich.org 70 i+ ret = 0; Err bitreich.org 70 i+ walk_snap(check_snap, &ret); Err bitreich.org 70 i+ if (ret != 0) Err bitreich.org 70 i+ errx(1, "%s or %s is corrupted", SNAPSF, STOREF); Err bitreich.org 70 i+ term(); Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 1diff --git a/dedup.1 b/dedup.1 /scm/dedup/file/dedup.1.gph bitreich.org 70 i@@ -1,62 +0,0 @@ Err bitreich.org 70 i-.Dd April 10, 2019 Err bitreich.org 70 i-.Dt DEDUP 1 Err bitreich.org 70 i-.Os Err bitreich.org 70 i-.Sh NAME Err bitreich.org 70 i-.Nm dedup Err bitreich.org 70 i-.Nd data deduplication program Err bitreich.org 70 i-.Sh SYNOPSIS Err bitreich.org 70 i-.Nm dedup Err bitreich.org 70 i-.Op Fl cilv Err bitreich.org 70 i-.Op Fl H Ar hash Err bitreich.org 70 i-.Op Fl Z Ar compressor Err bitreich.org 70 i-.Op Fl e Ar id Err bitreich.org 70 i-.Op Fl r Ar root Err bitreich.org 70 i-.Op Fl m Ar message Err bitreich.org 70 i-.Op file Err bitreich.org 70 i-.Sh DESCRIPTION Err bitreich.org 70 i-.Nm Err bitreich.org 70 i-deduplicates data from the specified Err bitreich.org 70 i-.Ar file . Err bitreich.org 70 i-If no Err bitreich.org 70 i-.Ar file Err bitreich.org 70 i-is specified then it reads from standard input. Err bitreich.org 70 i-.Pp Err bitreich.org 70 i-.Nm Err bitreich.org 70 i-does not track any file metadata so to deduplicate Err bitreich.org 70 i-directory trees, an archival tool like Err bitreich.org 70 i-.Xr tar 1 Err bitreich.org 70 i-should be used and piped into Err bitreich.org 70 i-.Nm . Err bitreich.org 70 i-.Sh OPTIONS Err bitreich.org 70 i-.Bl -tag -width "-Z compressor" Err bitreich.org 70 i-.It Fl H Ar hash Err bitreich.org 70 i-The cryptographic hash function used to identify Err bitreich.org 70 i-unique blocks in the store. Err bitreich.org 70 i-The supported hash functions are blake2b, blake2bp, blake2s and blake2sp. Err bitreich.org 70 i-This flag only has an effect when initializing the repository. Err bitreich.org 70 i-By default blake2b is used. Err bitreich.org 70 i-.It Fl Z Ar compressor Err bitreich.org 70 i-The compressor function used to compress the blocks Err bitreich.org 70 i-in the store. Err bitreich.org 70 i-The supported compressor functions are none, lz4 and snappy. Err bitreich.org 70 i-This flag only has an effect when initializing the repository. Err bitreich.org 70 i-By default lz4 is used. Err bitreich.org 70 i-.It Fl c Err bitreich.org 70 i-Perform a consistency check on the repository. Err bitreich.org 70 i-.It Fl i Err bitreich.org 70 i-Initialize the repository. Err bitreich.org 70 i-.It Fl l Err bitreich.org 70 i-List snapshots. Err bitreich.org 70 i-.It Fl v Err bitreich.org 70 i-Enable verbose mode. Err bitreich.org 70 i-.It Fl e Ar id Err bitreich.org 70 i-Extract snapshot with the specified id. Err bitreich.org 70 i-.It Fl r Ar root Err bitreich.org 70 i-Set the directory where the repository will be created. Err bitreich.org 70 i-By default the repository is created in the current directory. Err bitreich.org 70 i-.It Fl m Ar message Err bitreich.org 70 i-Attach a descriptive message to the snapshot. Err bitreich.org 70 i-.El Err bitreich.org 70 i-.Sh AUTHORS Err bitreich.org 70 i-.An Dimitris Papastamos Aq Mt sin@2f30.org , Err bitreich.org 70 i-.An z3bra Aq Mt contactatz3bradotorg . Err bitreich.org 70 1diff --git a/dedup.c b/dedup.c /scm/dedup/file/dedup.c.gph bitreich.org 70 i@@ -1,700 +0,0 @@ Err bitreich.org 70 i-#include Err bitreich.org 70 i-#include Err bitreich.org 70 i-#include Err bitreich.org 70 i- Err bitreich.org 70 i-#include Err bitreich.org 70 i-#include Err bitreich.org 70 i-#include Err bitreich.org 70 i-#include Err bitreich.org 70 i-#include Err bitreich.org 70 i-#include Err bitreich.org 70 i-#include Err bitreich.org 70 i- Err bitreich.org 70 i-#include "arg.h" Err bitreich.org 70 i-#include "blake2.h" Err bitreich.org 70 i-#include "dedup.h" Err bitreich.org 70 i- Err bitreich.org 70 i-#define SNAPSF ".snapshots" Err bitreich.org 70 i-#define STOREF ".store" Err bitreich.org 70 i- Err bitreich.org 70 i-enum { Err bitreich.org 70 i- WALK_CONTINUE, Err bitreich.org 70 i- WALK_STOP Err bitreich.org 70 i-}; Err bitreich.org 70 i- Err bitreich.org 70 i-struct extract_args { Err bitreich.org 70 i- uint8_t *md; Err bitreich.org 70 i- int fd; Err bitreich.org 70 i- int ret; Err bitreich.org 70 i-}; Err bitreich.org 70 i- Err bitreich.org 70 i-static struct snap_hdr snap_hdr; Err bitreich.org 70 i-static struct blk_hdr blk_hdr; Err bitreich.org 70 i-static struct icache *icache; Err bitreich.org 70 i-static int ifd; Err bitreich.org 70 i-static int sfd; Err bitreich.org 70 i-static int hash_algo = HASH_BLAKE2B; Err bitreich.org 70 i-static int compr_algo = COMPR_LZ4; Err bitreich.org 70 i- Err bitreich.org 70 i-int verbose; Err bitreich.org 70 i-char *argv0; Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-print_md(FILE *fp, uint8_t *md, size_t size) Err bitreich.org 70 i-{ Err bitreich.org 70 i- size_t i; Err bitreich.org 70 i- Err bitreich.org 70 i- for (i = 0; i < size; i++) Err bitreich.org 70 i- fprintf(fp, "%02x", md[i]); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-print_stats(struct stats *st) Err bitreich.org 70 i-{ Err bitreich.org 70 i- unsigned long long hits, misses; Err bitreich.org 70 i- double hitratio; Err bitreich.org 70 i- Err bitreich.org 70 i- if (st->nr_blks == 0) Err bitreich.org 70 i- return; Err bitreich.org 70 i- Err bitreich.org 70 i- fprintf(stderr, "Original size: %llu bytes\n", Err bitreich.org 70 i- (unsigned long long)st->orig_size); Err bitreich.org 70 i- fprintf(stderr, "Compressed size: %llu bytes\n", Err bitreich.org 70 i- (unsigned long long)st->compr_size); Err bitreich.org 70 i- fprintf(stderr, "Deduplicated size: %llu bytes\n", Err bitreich.org 70 i- (unsigned long long)st->dedup_size); Err bitreich.org 70 i- fprintf(stderr, "Deduplication ratio: %.2f\n", Err bitreich.org 70 i- (double)st->orig_size / st->dedup_size); Err bitreich.org 70 i- fprintf(stderr, "Min/avg/max block size: %llu/%llu/%llu bytes\n", Err bitreich.org 70 i- (unsigned long long)st->min_blk_size, Err bitreich.org 70 i- (unsigned long long)st->dedup_size / st->nr_blks, Err bitreich.org 70 i- (unsigned long long)st->max_blk_size); Err bitreich.org 70 i- fprintf(stderr, "Number of unique blocks: %llu\n", Err bitreich.org 70 i- (unsigned long long)st->nr_blks); Err bitreich.org 70 i- Err bitreich.org 70 i- icache_stats(icache, &hits, &misses); Err bitreich.org 70 i- if (hits == 0 && misses == 0) Err bitreich.org 70 i- hitratio = 0; Err bitreich.org 70 i- else Err bitreich.org 70 i- hitratio = (double)hits / (hits + misses); Err bitreich.org 70 i- Err bitreich.org 70 i- fprintf(stderr, "Index cache hit percentage: %.2f%%\n", Err bitreich.org 70 i- 100 * hitratio); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static struct snap * Err bitreich.org 70 i-alloc_snap(void) Err bitreich.org 70 i-{ Err bitreich.org 70 i- struct snap *snap; Err bitreich.org 70 i- Err bitreich.org 70 i- snap = calloc(1, sizeof(*snap)); Err bitreich.org 70 i- if (snap == NULL) Err bitreich.org 70 i- err(1, "%s", __func__); Err bitreich.org 70 i- return snap; Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-free_snap(struct snap *snap) Err bitreich.org 70 i-{ Err bitreich.org 70 i- free(snap); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-/* Err bitreich.org 70 i- * The snapshot hash is calculated over the Err bitreich.org 70 i- * hash of its block descriptors. Err bitreich.org 70 i- */ Err bitreich.org 70 i-static void Err bitreich.org 70 i-hash_snap(struct snap *snap, uint8_t *md) Err bitreich.org 70 i-{ Err bitreich.org 70 i- struct hash_ctx ctx; Err bitreich.org 70 i- uint64_t i; Err bitreich.org 70 i- Err bitreich.org 70 i- if (hash_init(&ctx, hash_algo, MD_SIZE) < 0) Err bitreich.org 70 i- errx(1, "hash_init failed"); Err bitreich.org 70 i- for (i = 0; i < snap->nr_blk_descs; i++) { Err bitreich.org 70 i- struct blk_desc *blk_desc; Err bitreich.org 70 i- Err bitreich.org 70 i- blk_desc = &snap->blk_desc[i]; Err bitreich.org 70 i- hash_update(&ctx, blk_desc->md, sizeof(blk_desc->md)); Err bitreich.org 70 i- } Err bitreich.org 70 i- hash_final(&ctx, md, MD_SIZE); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static struct snap * Err bitreich.org 70 i-grow_snap(struct snap *snap, uint64_t nr_blk_descs) Err bitreich.org 70 i-{ Err bitreich.org 70 i- size_t size; Err bitreich.org 70 i- Err bitreich.org 70 i- if (nr_blk_descs > SIZE_MAX / sizeof(snap->blk_desc[0])) Err bitreich.org 70 i- errx(1, "%s: overflow", __func__); Err bitreich.org 70 i- size = nr_blk_descs * sizeof(snap->blk_desc[0]); Err bitreich.org 70 i- Err bitreich.org 70 i- if (size > SIZE_MAX - sizeof(*snap)) Err bitreich.org 70 i- errx(1, "%s: overflow", __func__); Err bitreich.org 70 i- size += sizeof(*snap); Err bitreich.org 70 i- Err bitreich.org 70 i- snap = realloc(snap, size); Err bitreich.org 70 i- if (snap == NULL) Err bitreich.org 70 i- err(1, "%s", __func__); Err bitreich.org 70 i- return snap; Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-append_snap(struct snap *snap) Err bitreich.org 70 i-{ Err bitreich.org 70 i- if (snap->nr_blk_descs > UINT64_MAX / BLK_DESC_SIZE) Err bitreich.org 70 i- errx(1, "%s: overflow", __func__); Err bitreich.org 70 i- snap->size = snap->nr_blk_descs * BLK_DESC_SIZE; Err bitreich.org 70 i- Err bitreich.org 70 i- if (snap->size > UINT64_MAX - SNAPSHOT_SIZE) Err bitreich.org 70 i- errx(1, "%s: overflow", __func__); Err bitreich.org 70 i- snap->size += SNAPSHOT_SIZE; Err bitreich.org 70 i- Err bitreich.org 70 i- xlseek(ifd, snap_hdr.size, SEEK_SET); Err bitreich.org 70 i- write_snap(ifd, snap); Err bitreich.org 70 i- write_snap_blk_descs(ifd, snap); Err bitreich.org 70 i- Err bitreich.org 70 i- if (snap_hdr.size > UINT64_MAX - snap->size) Err bitreich.org 70 i- errx(1, "%s: overflow", __func__); Err bitreich.org 70 i- snap_hdr.size += snap->size; Err bitreich.org 70 i- Err bitreich.org 70 i- if (snap_hdr.nr_snaps > UINT64_MAX - 1) Err bitreich.org 70 i- errx(1, "%s: overflow", __func__); Err bitreich.org 70 i- snap_hdr.nr_snaps++; Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static uint8_t * Err bitreich.org 70 i-alloc_buf(size_t size) Err bitreich.org 70 i-{ Err bitreich.org 70 i- void *p; Err bitreich.org 70 i- Err bitreich.org 70 i- p = calloc(1, size); Err bitreich.org 70 i- if (p == NULL) Err bitreich.org 70 i- err(1, "%s", __func__); Err bitreich.org 70 i- return p; Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-free_buf(uint8_t *buf) Err bitreich.org 70 i-{ Err bitreich.org 70 i- free(buf); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-hash_blk(uint8_t *buf, size_t size, uint8_t *md) Err bitreich.org 70 i-{ Err bitreich.org 70 i- struct hash_ctx ctx; Err bitreich.org 70 i- Err bitreich.org 70 i- if (hash_init(&ctx, hash_algo, MD_SIZE) < 0) Err bitreich.org 70 i- errx(1, "hash_init failed"); Err bitreich.org 70 i- hash_update(&ctx, buf, size); Err bitreich.org 70 i- hash_final(&ctx, md, MD_SIZE); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-read_blk(uint8_t *buf, struct blk_desc *blk_desc) Err bitreich.org 70 i-{ Err bitreich.org 70 i- ssize_t n; Err bitreich.org 70 i- Err bitreich.org 70 i- xlseek(sfd, blk_desc->offset, SEEK_SET); Err bitreich.org 70 i- n = xread(sfd, buf, blk_desc->size); Err bitreich.org 70 i- if (n == 0) Err bitreich.org 70 i- errx(1, "%s: unexpected EOF", __func__); Err bitreich.org 70 i- if (n != blk_desc->size) Err bitreich.org 70 i- errx(1, "%s: short read", __func__); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-append_blk(uint8_t *buf, struct blk_desc *blk_desc) Err bitreich.org 70 i-{ Err bitreich.org 70 i- xlseek(sfd, blk_hdr.size, SEEK_SET); Err bitreich.org 70 i- xwrite(sfd, buf, blk_desc->size); Err bitreich.org 70 i- Err bitreich.org 70 i- if (blk_hdr.size > UINT64_MAX - blk_desc->size) Err bitreich.org 70 i- errx(1, "%s: overflow", __func__); Err bitreich.org 70 i- blk_hdr.size += blk_desc->size; Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-dedup_chunk(struct snap *snap, uint8_t *chunkp, size_t chunk_size) Err bitreich.org 70 i-{ Err bitreich.org 70 i- uint8_t md[MD_SIZE]; Err bitreich.org 70 i- struct blk_desc blk_desc; Err bitreich.org 70 i- struct compr_ctx ctx; Err bitreich.org 70 i- uint8_t *compr_buf; Err bitreich.org 70 i- size_t n, csize; Err bitreich.org 70 i- Err bitreich.org 70 i- if (compr_init(&ctx, compr_algo) < 0) Err bitreich.org 70 i- errx(1, "compr_init failed"); Err bitreich.org 70 i- csize = compr_size(&ctx, BLKSIZE_MAX); Err bitreich.org 70 i- compr_buf = alloc_buf(csize); Err bitreich.org 70 i- Err bitreich.org 70 i- n = compr(&ctx, chunkp, compr_buf, chunk_size, csize); Err bitreich.org 70 i- hash_blk(compr_buf, n, md); Err bitreich.org 70 i- Err bitreich.org 70 i- snap_hdr.st.orig_size += chunk_size; Err bitreich.org 70 i- snap_hdr.st.compr_size += n; Err bitreich.org 70 i- Err bitreich.org 70 i- memcpy(blk_desc.md, md, sizeof(blk_desc.md)); Err bitreich.org 70 i- if (lookup_icache(icache, &blk_desc) < 0) { Err bitreich.org 70 i- blk_desc.offset = blk_hdr.size; Err bitreich.org 70 i- blk_desc.size = n; Err bitreich.org 70 i- Err bitreich.org 70 i- snap->blk_desc[snap->nr_blk_descs++] = blk_desc; Err bitreich.org 70 i- append_blk(compr_buf, &blk_desc); Err bitreich.org 70 i- Err bitreich.org 70 i- insert_icache(icache, &blk_desc); Err bitreich.org 70 i- Err bitreich.org 70 i- snap_hdr.st.dedup_size += blk_desc.size; Err bitreich.org 70 i- snap_hdr.st.nr_blks++; Err bitreich.org 70 i- Err bitreich.org 70 i- if (blk_desc.size > snap_hdr.st.max_blk_size) Err bitreich.org 70 i- snap_hdr.st.max_blk_size = blk_desc.size; Err bitreich.org 70 i- if (blk_desc.size < snap_hdr.st.min_blk_size) Err bitreich.org 70 i- snap_hdr.st.min_blk_size = blk_desc.size; Err bitreich.org 70 i- } else { Err bitreich.org 70 i- snap->blk_desc[snap->nr_blk_descs++] = blk_desc; Err bitreich.org 70 i- } Err bitreich.org 70 i- Err bitreich.org 70 i- free(compr_buf); Err bitreich.org 70 i- compr_final(&ctx); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-dedup(int fd, char *msg) Err bitreich.org 70 i-{ Err bitreich.org 70 i- struct snap *snap; Err bitreich.org 70 i- struct chunker *chunker; Err bitreich.org 70 i- Err bitreich.org 70 i- snap = alloc_snap(); Err bitreich.org 70 i- chunker = alloc_chunker(fd, BLKSIZE_MIN, BLKSIZE_MAX, Err bitreich.org 70 i- HASHMASK_BITS, WINSIZE); Err bitreich.org 70 i- Err bitreich.org 70 i- while (fill_chunker(chunker) > 0) { Err bitreich.org 70 i- uint8_t *chunkp; Err bitreich.org 70 i- size_t chunk_size; Err bitreich.org 70 i- Err bitreich.org 70 i- chunkp = get_chunk(chunker, &chunk_size); Err bitreich.org 70 i- snap = grow_snap(snap, snap->nr_blk_descs + 1); Err bitreich.org 70 i- dedup_chunk(snap, chunkp, chunk_size); Err bitreich.org 70 i- drain_chunker(chunker); Err bitreich.org 70 i- } Err bitreich.org 70 i- Err bitreich.org 70 i- if (snap->nr_blk_descs > 0) { Err bitreich.org 70 i- if (msg != NULL) { Err bitreich.org 70 i- size_t size; Err bitreich.org 70 i- Err bitreich.org 70 i- size = strlen(msg) + 1; Err bitreich.org 70 i- if (size > sizeof(snap->msg)) Err bitreich.org 70 i- size = sizeof(snap->msg); Err bitreich.org 70 i- memcpy(snap->msg, msg, size); Err bitreich.org 70 i- snap->msg[size - 1] = '\0'; Err bitreich.org 70 i- } Err bitreich.org 70 i- hash_snap(snap, snap->md); Err bitreich.org 70 i- append_snap(snap); Err bitreich.org 70 i- } Err bitreich.org 70 i- Err bitreich.org 70 i- free_chunker(chunker); Err bitreich.org 70 i- free_snap(snap); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static int Err bitreich.org 70 i-extract(struct snap *snap, void *arg) Err bitreich.org 70 i-{ Err bitreich.org 70 i- uint8_t *buf[2]; Err bitreich.org 70 i- struct extract_args *args = arg; Err bitreich.org 70 i- struct compr_ctx ctx; Err bitreich.org 70 i- uint64_t i; Err bitreich.org 70 i- Err bitreich.org 70 i- if (memcmp(snap->md, args->md, sizeof(snap->md)) != 0) Err bitreich.org 70 i- return WALK_CONTINUE; Err bitreich.org 70 i- Err bitreich.org 70 i- if (compr_init(&ctx, compr_algo) < 0) Err bitreich.org 70 i- errx(1, "compr_init failed"); Err bitreich.org 70 i- buf[0] = alloc_buf(BLKSIZE_MAX); Err bitreich.org 70 i- buf[1] = alloc_buf(compr_size(&ctx, BLKSIZE_MAX)); Err bitreich.org 70 i- for (i = 0; i < snap->nr_blk_descs; i++) { Err bitreich.org 70 i- struct blk_desc *blk_desc; Err bitreich.org 70 i- size_t blksize; Err bitreich.org 70 i- Err bitreich.org 70 i- blk_desc = &snap->blk_desc[i]; Err bitreich.org 70 i- read_blk(buf[1], blk_desc); Err bitreich.org 70 i- blksize = decompr(&ctx, buf[1], buf[0], blk_desc->size, BLKSIZE_MAX); Err bitreich.org 70 i- xwrite(args->fd, buf[0], blksize); Err bitreich.org 70 i- } Err bitreich.org 70 i- free_buf(buf[1]); Err bitreich.org 70 i- free_buf(buf[0]); Err bitreich.org 70 i- compr_final(&ctx); Err bitreich.org 70 i- args->ret = 0; Err bitreich.org 70 i- return WALK_STOP; Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-/* Err bitreich.org 70 i- * Hash every block referenced by the given snapshot Err bitreich.org 70 i- * and compare its hash with the one stored in the corresponding Err bitreich.org 70 i- * block descriptor. Err bitreich.org 70 i- */ Err bitreich.org 70 i-static int Err bitreich.org 70 i-check_snap(struct snap *snap, void *arg) Err bitreich.org 70 i-{ Err bitreich.org 70 i- struct compr_ctx ctx; Err bitreich.org 70 i- uint8_t *buf; Err bitreich.org 70 i- int *ret = arg; Err bitreich.org 70 i- uint64_t i; Err bitreich.org 70 i- Err bitreich.org 70 i- if (verbose > 0) { Err bitreich.org 70 i- fprintf(stderr, "Checking snapshot: "); Err bitreich.org 70 i- print_md(stderr, snap->md, sizeof(snap->md)); Err bitreich.org 70 i- fputc('\n', stderr); Err bitreich.org 70 i- } Err bitreich.org 70 i- Err bitreich.org 70 i- if (compr_init(&ctx, compr_algo) < 0) Err bitreich.org 70 i- errx(1, "compr_init failed"); Err bitreich.org 70 i- buf = alloc_buf(compr_size(&ctx, BLKSIZE_MAX)); Err bitreich.org 70 i- for (i = 0; i < snap->nr_blk_descs; i++) { Err bitreich.org 70 i- uint8_t md[MD_SIZE]; Err bitreich.org 70 i- struct blk_desc *blk_desc; Err bitreich.org 70 i- Err bitreich.org 70 i- blk_desc = &snap->blk_desc[i]; Err bitreich.org 70 i- read_blk(buf, blk_desc); Err bitreich.org 70 i- hash_blk(buf, blk_desc->size, md); Err bitreich.org 70 i- Err bitreich.org 70 i- if (memcmp(blk_desc->md, md, sizeof(blk_desc->md)) == 0) Err bitreich.org 70 i- continue; Err bitreich.org 70 i- Err bitreich.org 70 i- fprintf(stderr, "Block hash mismatch\n"); Err bitreich.org 70 i- fprintf(stderr, " Expected hash: "); Err bitreich.org 70 i- print_md(stderr, blk_desc->md, sizeof(blk_desc->md)); Err bitreich.org 70 i- fputc('\n', stderr); Err bitreich.org 70 i- fprintf(stderr, " Actual hash: "); Err bitreich.org 70 i- print_md(stderr, md, sizeof(md)); Err bitreich.org 70 i- fputc('\n', stderr); Err bitreich.org 70 i- fprintf(stderr, " Offset: %llu\n", Err bitreich.org 70 i- (unsigned long long)blk_desc->offset); Err bitreich.org 70 i- fprintf(stderr, " Size: %llu\n", Err bitreich.org 70 i- (unsigned long long)blk_desc->size); Err bitreich.org 70 i- *ret = -1; Err bitreich.org 70 i- } Err bitreich.org 70 i- free_buf(buf); Err bitreich.org 70 i- compr_final(&ctx); Err bitreich.org 70 i- return WALK_CONTINUE; Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static int Err bitreich.org 70 i-build_icache(struct snap *snap, void *arg) Err bitreich.org 70 i-{ Err bitreich.org 70 i- struct compr_ctx ctx; Err bitreich.org 70 i- uint8_t *buf; Err bitreich.org 70 i- uint64_t i; Err bitreich.org 70 i- Err bitreich.org 70 i- if (compr_init(&ctx, compr_algo) < 0) Err bitreich.org 70 i- errx(1, "compr_init failed"); Err bitreich.org 70 i- buf = alloc_buf(compr_size(&ctx, BLKSIZE_MAX)); Err bitreich.org 70 i- for (i = 0; i < snap->nr_blk_descs; i++) { Err bitreich.org 70 i- struct blk_desc *blk_desc; Err bitreich.org 70 i- Err bitreich.org 70 i- blk_desc = &snap->blk_desc[i]; Err bitreich.org 70 i- insert_icache(icache, blk_desc); Err bitreich.org 70 i- } Err bitreich.org 70 i- free(buf); Err bitreich.org 70 i- compr_final(&ctx); Err bitreich.org 70 i- return WALK_CONTINUE; Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static int Err bitreich.org 70 i-list(struct snap *snap, void *arg) Err bitreich.org 70 i-{ Err bitreich.org 70 i- print_md(stdout, snap->md, sizeof(snap->md)); Err bitreich.org 70 i- if (snap->msg[0] != '\0') Err bitreich.org 70 i- printf("\t%s\n", snap->msg); Err bitreich.org 70 i- else Err bitreich.org 70 i- putchar('\n'); Err bitreich.org 70 i- return WALK_CONTINUE; Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-/* Walk through all snapshots and call fn() on each one */ Err bitreich.org 70 i-static void Err bitreich.org 70 i-walk_snap(int (*fn)(struct snap *, void *), void *arg) Err bitreich.org 70 i-{ Err bitreich.org 70 i- uint64_t i; Err bitreich.org 70 i- Err bitreich.org 70 i- xlseek(ifd, SNAP_HDR_SIZE, SEEK_SET); Err bitreich.org 70 i- for (i = 0; i < snap_hdr.nr_snaps; i++) { Err bitreich.org 70 i- struct snap *snap; Err bitreich.org 70 i- int ret; Err bitreich.org 70 i- Err bitreich.org 70 i- snap = alloc_snap(); Err bitreich.org 70 i- read_snap(ifd, snap); Err bitreich.org 70 i- snap = grow_snap(snap, snap->nr_blk_descs); Err bitreich.org 70 i- read_snap_descs(ifd, snap); Err bitreich.org 70 i- Err bitreich.org 70 i- ret = (*fn)(snap, arg); Err bitreich.org 70 i- free_snap(snap); Err bitreich.org 70 i- if (ret == WALK_STOP) Err bitreich.org 70 i- break; Err bitreich.org 70 i- } Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-match_ver(uint64_t v) Err bitreich.org 70 i-{ Err bitreich.org 70 i- uint8_t maj, min; Err bitreich.org 70 i- Err bitreich.org 70 i- min = v & VER_MIN_MASK; Err bitreich.org 70 i- maj = (v >> VER_MAJ_SHIFT) & VER_MAJ_MASK; Err bitreich.org 70 i- if (maj == VER_MAJ && min == VER_MIN) Err bitreich.org 70 i- return; Err bitreich.org 70 i- errx(1, "format version mismatch: expected %u.%u but got %u.%u", Err bitreich.org 70 i- VER_MAJ, VER_MIN, maj, min); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-init_blk_hdr(void) Err bitreich.org 70 i-{ Err bitreich.org 70 i- blk_hdr.flags = (VER_MAJ << VER_MAJ_SHIFT) | VER_MIN; Err bitreich.org 70 i- blk_hdr.flags |= compr_algo << COMPR_ALGO_SHIFT; Err bitreich.org 70 i- blk_hdr.flags |= hash_algo << HASH_ALGO_SHIFT; Err bitreich.org 70 i- blk_hdr.size = BLK_HDR_SIZE; Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-load_blk_hdr(void) Err bitreich.org 70 i-{ Err bitreich.org 70 i- uint64_t v; Err bitreich.org 70 i- Err bitreich.org 70 i- xlseek(sfd, 0, SEEK_SET); Err bitreich.org 70 i- read_blk_hdr(sfd, &blk_hdr); Err bitreich.org 70 i- match_ver(blk_hdr.flags); Err bitreich.org 70 i- Err bitreich.org 70 i- v = blk_hdr.flags >> COMPR_ALGO_SHIFT; Err bitreich.org 70 i- v &= COMPR_ALGO_MASK; Err bitreich.org 70 i- compr_algo = v; Err bitreich.org 70 i- Err bitreich.org 70 i- if (compr_algo < 0 || compr_algo >= NR_COMPRS) Err bitreich.org 70 i- errx(1, "unsupported compression algorithm: %d", compr_algo); Err bitreich.org 70 i- Err bitreich.org 70 i- if (verbose > 0) Err bitreich.org 70 i- fprintf(stderr, "Compression algorithm: %s\n", Err bitreich.org 70 i- compr_type2name(compr_algo)); Err bitreich.org 70 i- Err bitreich.org 70 i- v = blk_hdr.flags >> HASH_ALGO_SHIFT; Err bitreich.org 70 i- v &= HASH_ALGO_MASK; Err bitreich.org 70 i- hash_algo = v; Err bitreich.org 70 i- Err bitreich.org 70 i- if (hash_algo < 0 || hash_algo >= NR_HASHES) Err bitreich.org 70 i- errx(1, "unsupported hash algorithm: %d", hash_algo); Err bitreich.org 70 i- Err bitreich.org 70 i- if (verbose > 0) Err bitreich.org 70 i- fprintf(stderr, "Hash algorithm: %s\n", Err bitreich.org 70 i- hash_type2name(hash_algo)); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-save_blk_hdr(void) Err bitreich.org 70 i-{ Err bitreich.org 70 i- xlseek(sfd, 0, SEEK_SET); Err bitreich.org 70 i- write_blk_hdr(sfd, &blk_hdr); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-init_snap_hdr(void) Err bitreich.org 70 i-{ Err bitreich.org 70 i- snap_hdr.flags = (VER_MAJ << VER_MAJ_SHIFT) | VER_MIN; Err bitreich.org 70 i- snap_hdr.size = SNAP_HDR_SIZE; Err bitreich.org 70 i- snap_hdr.st.min_blk_size = UINT64_MAX; Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-load_snap_hdr(void) Err bitreich.org 70 i-{ Err bitreich.org 70 i- xlseek(ifd, 0, SEEK_SET); Err bitreich.org 70 i- read_snap_hdr(ifd, &snap_hdr); Err bitreich.org 70 i- match_ver(snap_hdr.flags); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-save_snap_hdr(void) Err bitreich.org 70 i-{ Err bitreich.org 70 i- xlseek(ifd, 0, SEEK_SET); Err bitreich.org 70 i- write_snap_hdr(ifd, &snap_hdr); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-init(int iflag) Err bitreich.org 70 i-{ Err bitreich.org 70 i- int flags; Err bitreich.org 70 i- Err bitreich.org 70 i- flags = O_RDWR; Err bitreich.org 70 i- if (iflag) Err bitreich.org 70 i- flags |= O_CREAT | O_EXCL; Err bitreich.org 70 i- Err bitreich.org 70 i- ifd = open(SNAPSF, flags, 0600); Err bitreich.org 70 i- if (ifd < 0) Err bitreich.org 70 i- err(1, "open %s", SNAPSF); Err bitreich.org 70 i- Err bitreich.org 70 i- sfd = open(STOREF, flags, 0600); Err bitreich.org 70 i- if (sfd < 0) Err bitreich.org 70 i- err(1, "open %s", STOREF); Err bitreich.org 70 i- Err bitreich.org 70 i- if (flock(ifd, LOCK_NB | LOCK_EX) < 0 || Err bitreich.org 70 i- flock(sfd, LOCK_NB | LOCK_EX) < 0) Err bitreich.org 70 i- err(1, "flock"); Err bitreich.org 70 i- Err bitreich.org 70 i- if (iflag) { Err bitreich.org 70 i- init_snap_hdr(); Err bitreich.org 70 i- init_blk_hdr(); Err bitreich.org 70 i- } else { Err bitreich.org 70 i- load_snap_hdr(); Err bitreich.org 70 i- load_blk_hdr(); Err bitreich.org 70 i- } Err bitreich.org 70 i- Err bitreich.org 70 i- icache = alloc_icache(); Err bitreich.org 70 i- walk_snap(build_icache, NULL); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-term(void) Err bitreich.org 70 i-{ Err bitreich.org 70 i- if (verbose > 0) Err bitreich.org 70 i- print_stats(&snap_hdr.st); Err bitreich.org 70 i- Err bitreich.org 70 i- free_icache(icache); Err bitreich.org 70 i- Err bitreich.org 70 i- save_blk_hdr(); Err bitreich.org 70 i- save_snap_hdr(); Err bitreich.org 70 i- Err bitreich.org 70 i- fsync(sfd); Err bitreich.org 70 i- fsync(ifd); Err bitreich.org 70 i- Err bitreich.org 70 i- close(sfd); Err bitreich.org 70 i- close(ifd); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-static void Err bitreich.org 70 i-usage(void) Err bitreich.org 70 i-{ Err bitreich.org 70 i- fprintf(stderr, "usage: %s [-cilv] [-H hash] [-Z compressor] [-e id] [-r root] [-m message] [file]\n", argv0); Err bitreich.org 70 i- exit(1); Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i-int Err bitreich.org 70 i-main(int argc, char *argv[]) Err bitreich.org 70 i-{ Err bitreich.org 70 i- uint8_t md[MD_SIZE]; Err bitreich.org 70 i- char *id = NULL, *root = NULL, *msg = NULL, *hash_name, *compr_name; Err bitreich.org 70 i- int iflag = 0, lflag = 0, cflag = 0; Err bitreich.org 70 i- int fd = -1; Err bitreich.org 70 i- Err bitreich.org 70 i- ARGBEGIN { Err bitreich.org 70 i- case 'H': Err bitreich.org 70 i- hash_name = EARGF(usage()); Err bitreich.org 70 i- if (strcmp(hash_name, "?") == 0) { Err bitreich.org 70 i- hash_list(STDERR_FILENO); Err bitreich.org 70 i- return 0; Err bitreich.org 70 i- } Err bitreich.org 70 i- hash_algo = hash_name2type(hash_name); Err bitreich.org 70 i- if (hash_algo < 0) Err bitreich.org 70 i- errx(1, "unknown hash: %s", hash_name); Err bitreich.org 70 i- break; Err bitreich.org 70 i- case 'Z': Err bitreich.org 70 i- compr_name = EARGF(usage()); Err bitreich.org 70 i- if (strcmp(compr_name, "?") == 0) { Err bitreich.org 70 i- compr_list(STDERR_FILENO); Err bitreich.org 70 i- return 0; Err bitreich.org 70 i- } Err bitreich.org 70 i- compr_algo = compr_name2type(compr_name); Err bitreich.org 70 i- if (compr_algo < 0) Err bitreich.org 70 i- errx(1, "unknown compressor: %s", compr_name); Err bitreich.org 70 i- break; Err bitreich.org 70 i- case 'c': Err bitreich.org 70 i- cflag = 1; Err bitreich.org 70 i- break; Err bitreich.org 70 i- case 'e': Err bitreich.org 70 i- id = EARGF(usage()); Err bitreich.org 70 i- break; Err bitreich.org 70 i- case 'i': Err bitreich.org 70 i- iflag = 1; Err bitreich.org 70 i- break; Err bitreich.org 70 i- case 'l': Err bitreich.org 70 i- lflag = 1; Err bitreich.org 70 i- break; Err bitreich.org 70 i- case 'r': Err bitreich.org 70 i- root = EARGF(usage()); Err bitreich.org 70 i- break; Err bitreich.org 70 i- case 'm': Err bitreich.org 70 i- msg = EARGF(usage()); Err bitreich.org 70 i- break; Err bitreich.org 70 i- case 'v': Err bitreich.org 70 i- verbose++; Err bitreich.org 70 i- break; Err bitreich.org 70 i- default: Err bitreich.org 70 i- usage(); Err bitreich.org 70 i- } ARGEND Err bitreich.org 70 i- Err bitreich.org 70 i- if (argc > 1) { Err bitreich.org 70 i- usage(); Err bitreich.org 70 i- } else if (argc == 1) { Err bitreich.org 70 i- if (id) { Err bitreich.org 70 i- fd = open(argv[0], O_RDWR | O_CREAT, 0600); Err bitreich.org 70 i- if (fd < 0) Err bitreich.org 70 i- err(1, "open %s", argv[0]); Err bitreich.org 70 i- } else { Err bitreich.org 70 i- fd = open(argv[0], O_RDONLY); Err bitreich.org 70 i- if (fd < 0) Err bitreich.org 70 i- err(1, "open %s", argv[0]); Err bitreich.org 70 i- } Err bitreich.org 70 i- } else { Err bitreich.org 70 i- if (id) Err bitreich.org 70 i- fd = STDOUT_FILENO; Err bitreich.org 70 i- else Err bitreich.org 70 i- fd = STDIN_FILENO; Err bitreich.org 70 i- } Err bitreich.org 70 i- Err bitreich.org 70 i- if (root != NULL) { Err bitreich.org 70 i- mkdir(root, 0700); Err bitreich.org 70 i- if (chdir(root) < 0) Err bitreich.org 70 i- err(1, "chdir: %s", root); Err bitreich.org 70 i- } Err bitreich.org 70 i- Err bitreich.org 70 i- init(iflag); Err bitreich.org 70 i- Err bitreich.org 70 i- if (iflag) { Err bitreich.org 70 i- term(); Err bitreich.org 70 i- return 0; Err bitreich.org 70 i- } Err bitreich.org 70 i- Err bitreich.org 70 i- if (cflag) { Err bitreich.org 70 i- int ret; Err bitreich.org 70 i- Err bitreich.org 70 i- ret = 0; Err bitreich.org 70 i- walk_snap(check_snap, &ret); Err bitreich.org 70 i- if (ret != 0) Err bitreich.org 70 i- errx(1, "%s or %s is corrupted", SNAPSF, STOREF); Err bitreich.org 70 i- Err bitreich.org 70 i- term(); Err bitreich.org 70 i- return 0; Err bitreich.org 70 i- } Err bitreich.org 70 i- Err bitreich.org 70 i- if (lflag) { Err bitreich.org 70 i- walk_snap(list, NULL); Err bitreich.org 70 i- term(); Err bitreich.org 70 i- return 0; Err bitreich.org 70 i- } Err bitreich.org 70 i- Err bitreich.org 70 i- if (id) { Err bitreich.org 70 i- struct extract_args args; Err bitreich.org 70 i- Err bitreich.org 70 i- str2bin(id, md); Err bitreich.org 70 i- args.md = md; Err bitreich.org 70 i- args.fd = fd; Err bitreich.org 70 i- args.ret = -1; Err bitreich.org 70 i- walk_snap(extract, &args); Err bitreich.org 70 i- if (args.ret != 0) Err bitreich.org 70 i- errx(1, "unknown snapshot: %s", id); Err bitreich.org 70 i- } else { Err bitreich.org 70 i- dedup(fd, msg); Err bitreich.org 70 i- } Err bitreich.org 70 i- Err bitreich.org 70 i- term(); Err bitreich.org 70 i- return 0; Err bitreich.org 70 i-} Err bitreich.org 70 1diff --git a/dinfo.1 b/dinfo.1 /scm/dedup/file/dinfo.1.gph bitreich.org 70 i@@ -0,0 +1,25 @@ Err bitreich.org 70 i+.Dd April 17, 2019 Err bitreich.org 70 i+.Dt DINFO 1 Err bitreich.org 70 i+.Os Err bitreich.org 70 i+.Sh NAME Err bitreich.org 70 i+.Nm dinfo Err bitreich.org 70 i+.Nd Print information about a dedup repository Err bitreich.org 70 i+.Sh SYNOPSIS Err bitreich.org 70 i+.Nm dinfo Err bitreich.org 70 i+.Op Fl v Err bitreich.org 70 i+.Op repo Err bitreich.org 70 i+.Sh DESCRIPTION Err bitreich.org 70 i+.Nm Err bitreich.org 70 i+prints information about a dedup repository. Err bitreich.org 70 i+If no Err bitreich.org 70 i+.Ar repo Err bitreich.org 70 i+is specified, then the current directory Err bitreich.org 70 i+is assumed to be the repository. Err bitreich.org 70 i+.Sh OPTIONS Err bitreich.org 70 i+.Bl -tag -width "-v" Err bitreich.org 70 i+.It Fl v Err bitreich.org 70 i+Enable verbose mode. Err bitreich.org 70 i+.El Err bitreich.org 70 i+.Sh AUTHORS Err bitreich.org 70 i+.An Dimitris Papastamos Aq Mt sin@2f30.org , Err bitreich.org 70 i+.An z3bra Aq Mt contactatz3bradotorg . Err bitreich.org 70 1diff --git a/dinfo.c b/dinfo.c /scm/dedup/file/dinfo.c.gph bitreich.org 70 i@@ -0,0 +1,170 @@ Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+#include "arg.h" Err bitreich.org 70 i+#include "blake2.h" Err bitreich.org 70 i+#include "dedup.h" Err bitreich.org 70 i+ Err bitreich.org 70 i+#define SNAPSF ".snapshots" Err bitreich.org 70 i+#define STOREF ".store" Err bitreich.org 70 i+ Err bitreich.org 70 i+static struct snap_hdr snap_hdr; Err bitreich.org 70 i+static struct blk_hdr blk_hdr; Err bitreich.org 70 i+static int ifd; Err bitreich.org 70 i+static int sfd; Err bitreich.org 70 i+static int hash_algo = HASH_BLAKE2B; Err bitreich.org 70 i+static int compr_algo = COMPR_LZ4; Err bitreich.org 70 i+ Err bitreich.org 70 i+int verbose; Err bitreich.org 70 i+char *argv0; Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+print_info(struct stats *st) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ if (st->nr_blks == 0) Err bitreich.org 70 i+ return; Err bitreich.org 70 i+ Err bitreich.org 70 i+ fprintf(stderr, "Original size: %llu bytes\n", Err bitreich.org 70 i+ (unsigned long long)st->orig_size); Err bitreich.org 70 i+ fprintf(stderr, "Compressed size: %llu bytes\n", Err bitreich.org 70 i+ (unsigned long long)st->compr_size); Err bitreich.org 70 i+ fprintf(stderr, "Deduplicated size: %llu bytes\n", Err bitreich.org 70 i+ (unsigned long long)st->dedup_size); Err bitreich.org 70 i+ fprintf(stderr, "Deduplication ratio: %.2f\n", Err bitreich.org 70 i+ (double)st->orig_size / st->dedup_size); Err bitreich.org 70 i+ fprintf(stderr, "Min/avg/max block size: %llu/%llu/%llu bytes\n", Err bitreich.org 70 i+ (unsigned long long)st->min_blk_size, Err bitreich.org 70 i+ (unsigned long long)st->dedup_size / st->nr_blks, Err bitreich.org 70 i+ (unsigned long long)st->max_blk_size); Err bitreich.org 70 i+ fprintf(stderr, "Number of unique blocks: %llu\n", Err bitreich.org 70 i+ (unsigned long long)st->nr_blks); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+match_ver(uint64_t v) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ uint8_t maj, min; Err bitreich.org 70 i+ Err bitreich.org 70 i+ min = v & VER_MIN_MASK; Err bitreich.org 70 i+ maj = (v >> VER_MAJ_SHIFT) & VER_MAJ_MASK; Err bitreich.org 70 i+ if (maj == VER_MAJ && min == VER_MIN) Err bitreich.org 70 i+ return; Err bitreich.org 70 i+ errx(1, "format version mismatch: expected %u.%u but got %u.%u", Err bitreich.org 70 i+ VER_MAJ, VER_MIN, maj, min); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+load_blk_hdr(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ uint64_t v; Err bitreich.org 70 i+ Err bitreich.org 70 i+ xlseek(sfd, 0, SEEK_SET); Err bitreich.org 70 i+ read_blk_hdr(sfd, &blk_hdr); Err bitreich.org 70 i+ match_ver(blk_hdr.flags); Err bitreich.org 70 i+ Err bitreich.org 70 i+ v = blk_hdr.flags >> COMPR_ALGO_SHIFT; Err bitreich.org 70 i+ v &= COMPR_ALGO_MASK; Err bitreich.org 70 i+ compr_algo = v; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (compr_algo < 0 || compr_algo >= NR_COMPRS) Err bitreich.org 70 i+ errx(1, "unsupported compression algorithm: %d", compr_algo); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (verbose > 0) Err bitreich.org 70 i+ fprintf(stderr, "Compression algorithm: %s\n", Err bitreich.org 70 i+ compr_type2name(compr_algo)); Err bitreich.org 70 i+ Err bitreich.org 70 i+ v = blk_hdr.flags >> HASH_ALGO_SHIFT; Err bitreich.org 70 i+ v &= HASH_ALGO_MASK; Err bitreich.org 70 i+ hash_algo = v; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (hash_algo < 0 || hash_algo >= NR_HASHES) Err bitreich.org 70 i+ errx(1, "unsupported hash algorithm: %d", hash_algo); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (verbose > 0) Err bitreich.org 70 i+ fprintf(stderr, "Hash algorithm: %s\n", Err bitreich.org 70 i+ hash_type2name(hash_algo)); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+load_snap_hdr(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ xlseek(ifd, 0, SEEK_SET); Err bitreich.org 70 i+ read_snap_hdr(ifd, &snap_hdr); Err bitreich.org 70 i+ match_ver(snap_hdr.flags); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+init(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ ifd = open(SNAPSF, O_RDONLY, 0600); Err bitreich.org 70 i+ if (ifd < 0) Err bitreich.org 70 i+ err(1, "open %s", SNAPSF); Err bitreich.org 70 i+ Err bitreich.org 70 i+ sfd = open(STOREF, O_RDONLY, 0600); Err bitreich.org 70 i+ if (sfd < 0) Err bitreich.org 70 i+ err(1, "open %s", STOREF); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (flock(ifd, LOCK_NB | LOCK_EX) < 0 || Err bitreich.org 70 i+ flock(sfd, LOCK_NB | LOCK_EX) < 0) Err bitreich.org 70 i+ err(1, "flock"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ load_snap_hdr(); Err bitreich.org 70 i+ load_blk_hdr(); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+term(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ close(sfd); Err bitreich.org 70 i+ close(ifd); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+usage(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ fprintf(stderr, "usage: %s [-v] [repo]\n", argv0); Err bitreich.org 70 i+ exit(1); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+main(int argc, char *argv[]) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ char *repo = NULL; Err bitreich.org 70 i+ Err bitreich.org 70 i+ ARGBEGIN { Err bitreich.org 70 i+ case 'v': Err bitreich.org 70 i+ verbose++; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ default: Err bitreich.org 70 i+ usage(); Err bitreich.org 70 i+ } ARGEND Err bitreich.org 70 i+ Err bitreich.org 70 i+ switch (argc) { Err bitreich.org 70 i+ case 0: Err bitreich.org 70 i+ repo = "."; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case 1: Err bitreich.org 70 i+ repo = argv[0]; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ default: Err bitreich.org 70 i+ usage(); Err bitreich.org 70 i+ }; Err bitreich.org 70 i+ Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (chdir(repo) < 0) Err bitreich.org 70 i+ err(1, "chdir: %s", repo); Err bitreich.org 70 i+ Err bitreich.org 70 i+ init(); Err bitreich.org 70 i+ print_info(&snap_hdr.st); Err bitreich.org 70 i+ term(); Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 1diff --git a/dinit.1 b/dinit.1 /scm/dedup/file/dinit.1.gph bitreich.org 70 i@@ -0,0 +1,39 @@ Err bitreich.org 70 i+.Dd April 17, 2019 Err bitreich.org 70 i+.Dt DINIT 1 Err bitreich.org 70 i+.Os Err bitreich.org 70 i+.Sh NAME Err bitreich.org 70 i+.Nm dinit Err bitreich.org 70 i+.Nd Initialize a dedup repository Err bitreich.org 70 i+.Sh SYNOPSIS Err bitreich.org 70 i+.Nm dinit Err bitreich.org 70 i+.Op Fl v Err bitreich.org 70 i+.Op Fl H Ar hash Err bitreich.org 70 i+.Op Fl Z Ar compressor Err bitreich.org 70 i+.Op repo Err bitreich.org 70 i+.Sh DESCRIPTION Err bitreich.org 70 i+.Nm Err bitreich.org 70 i+initializes a dedup repository. Err bitreich.org 70 i+If no Err bitreich.org 70 i+.Ar repo Err bitreich.org 70 i+is specified, then the current directory Err bitreich.org 70 i+is assumed to be the repository. Err bitreich.org 70 i+.Sh OPTIONS Err bitreich.org 70 i+.Bl -tag -width "-Z compressor" Err bitreich.org 70 i+.It Fl v Err bitreich.org 70 i+Enable verbose mode. Err bitreich.org 70 i+.It Fl H Ar hash Err bitreich.org 70 i+The cryptographic hash function used to identify Err bitreich.org 70 i+unique blocks in the store. Err bitreich.org 70 i+The supported hash functions are blake2b, blake2bp, blake2s and blake2sp. Err bitreich.org 70 i+This flag only has an effect when initializing the repository. Err bitreich.org 70 i+By default blake2b is used. Err bitreich.org 70 i+.It Fl Z Ar compressor Err bitreich.org 70 i+The compressor function used to compress the blocks Err bitreich.org 70 i+in the store. Err bitreich.org 70 i+The supported compressor functions are none, lz4 and snappy. Err bitreich.org 70 i+This flag only has an effect when initializing the repository. Err bitreich.org 70 i+By default lz4 is used. Err bitreich.org 70 i+.El Err bitreich.org 70 i+.Sh AUTHORS Err bitreich.org 70 i+.An Dimitris Papastamos Aq Mt sin@2f30.org , Err bitreich.org 70 i+.An z3bra Aq Mt contactatz3bradotorg . Err bitreich.org 70 1diff --git a/dinit.c b/dinit.c /scm/dedup/file/dinit.c.gph bitreich.org 70 i@@ -0,0 +1,155 @@ Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+#include "arg.h" Err bitreich.org 70 i+#include "blake2.h" Err bitreich.org 70 i+#include "dedup.h" Err bitreich.org 70 i+ Err bitreich.org 70 i+#define SNAPSF ".snapshots" Err bitreich.org 70 i+#define STOREF ".store" Err bitreich.org 70 i+ Err bitreich.org 70 i+static struct snap_hdr snap_hdr; Err bitreich.org 70 i+static struct blk_hdr blk_hdr; Err bitreich.org 70 i+static int ifd; Err bitreich.org 70 i+static int sfd; Err bitreich.org 70 i+static int hash_algo = HASH_BLAKE2B; Err bitreich.org 70 i+static int compr_algo = COMPR_LZ4; Err bitreich.org 70 i+ Err bitreich.org 70 i+int verbose; Err bitreich.org 70 i+char *argv0; Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+init_blk_hdr(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ blk_hdr.flags = (VER_MAJ << VER_MAJ_SHIFT) | VER_MIN; Err bitreich.org 70 i+ blk_hdr.flags |= compr_algo << COMPR_ALGO_SHIFT; Err bitreich.org 70 i+ blk_hdr.flags |= hash_algo << HASH_ALGO_SHIFT; Err bitreich.org 70 i+ blk_hdr.size = BLK_HDR_SIZE; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+save_blk_hdr(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ xlseek(sfd, 0, SEEK_SET); Err bitreich.org 70 i+ write_blk_hdr(sfd, &blk_hdr); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+init_snap_hdr(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ snap_hdr.flags = (VER_MAJ << VER_MAJ_SHIFT) | VER_MIN; Err bitreich.org 70 i+ snap_hdr.size = SNAP_HDR_SIZE; Err bitreich.org 70 i+ snap_hdr.st.min_blk_size = UINT64_MAX; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+save_snap_hdr(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ xlseek(ifd, 0, SEEK_SET); Err bitreich.org 70 i+ write_snap_hdr(ifd, &snap_hdr); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+init(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ int flags; Err bitreich.org 70 i+ Err bitreich.org 70 i+ flags = O_RDWR | O_CREAT | O_EXCL; Err bitreich.org 70 i+ ifd = open(SNAPSF, flags, 0600); Err bitreich.org 70 i+ if (ifd < 0) Err bitreich.org 70 i+ err(1, "open %s", SNAPSF); Err bitreich.org 70 i+ Err bitreich.org 70 i+ sfd = open(STOREF, flags, 0600); Err bitreich.org 70 i+ if (sfd < 0) Err bitreich.org 70 i+ err(1, "open %s", STOREF); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (flock(ifd, LOCK_NB | LOCK_EX) < 0 || Err bitreich.org 70 i+ flock(sfd, LOCK_NB | LOCK_EX) < 0) Err bitreich.org 70 i+ err(1, "flock"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ init_snap_hdr(); Err bitreich.org 70 i+ init_blk_hdr(); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+term(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ save_blk_hdr(); Err bitreich.org 70 i+ save_snap_hdr(); Err bitreich.org 70 i+ Err bitreich.org 70 i+ fsync(sfd); Err bitreich.org 70 i+ fsync(ifd); Err bitreich.org 70 i+ Err bitreich.org 70 i+ close(sfd); Err bitreich.org 70 i+ close(ifd); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+usage(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ fprintf(stderr, "usage: %s [-v] [-H hash] [-Z compressor] [repo]\n", argv0); Err bitreich.org 70 i+ exit(1); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+main(int argc, char *argv[]) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ char *hash_name = NULL, *compr_name = NULL; Err bitreich.org 70 i+ char *repo; Err bitreich.org 70 i+ Err bitreich.org 70 i+ ARGBEGIN { Err bitreich.org 70 i+ case 'H': Err bitreich.org 70 i+ hash_name = EARGF(usage()); Err bitreich.org 70 i+ if (strcmp(hash_name, "?") == 0) { Err bitreich.org 70 i+ hash_list(STDERR_FILENO); Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ hash_algo = hash_name2type(hash_name); Err bitreich.org 70 i+ if (hash_algo < 0) Err bitreich.org 70 i+ errx(1, "unknown hash: %s", hash_name); Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case 'Z': Err bitreich.org 70 i+ compr_name = EARGF(usage()); Err bitreich.org 70 i+ if (strcmp(compr_name, "?") == 0) { Err bitreich.org 70 i+ compr_list(STDERR_FILENO); Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ compr_algo = compr_name2type(compr_name); Err bitreich.org 70 i+ if (compr_algo < 0) Err bitreich.org 70 i+ errx(1, "unknown compressor: %s", compr_name); Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case 'v': Err bitreich.org 70 i+ verbose++; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ default: Err bitreich.org 70 i+ usage(); Err bitreich.org 70 i+ } ARGEND Err bitreich.org 70 i+ Err bitreich.org 70 i+ switch (argc) { Err bitreich.org 70 i+ case 0: Err bitreich.org 70 i+ repo = "."; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case 1: Err bitreich.org 70 i+ repo = argv[0]; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ default: Err bitreich.org 70 i+ usage(); Err bitreich.org 70 i+ }; Err bitreich.org 70 i+ Err bitreich.org 70 i+ mkdir(repo, 0700); Err bitreich.org 70 i+ if (chdir(repo) < 0) Err bitreich.org 70 i+ err(1, "chdir: %s", repo); Err bitreich.org 70 i+ Err bitreich.org 70 i+ init(); Err bitreich.org 70 i+ term(); Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 1diff --git a/dlist.1 b/dlist.1 /scm/dedup/file/dlist.1.gph bitreich.org 70 i@@ -0,0 +1,25 @@ Err bitreich.org 70 i+.Dd April 17, 2019 Err bitreich.org 70 i+.Dt DLIST 1 Err bitreich.org 70 i+.Os Err bitreich.org 70 i+.Sh NAME Err bitreich.org 70 i+.Nm dlist Err bitreich.org 70 i+.Nd List snapshots from a dedup repository Err bitreich.org 70 i+.Sh SYNOPSIS Err bitreich.org 70 i+.Nm dlist Err bitreich.org 70 i+.Op Fl v Err bitreich.org 70 i+.Op repo Err bitreich.org 70 i+.Sh DESCRIPTION Err bitreich.org 70 i+.Nm Err bitreich.org 70 i+lists snapshots from a dedup repository. Err bitreich.org 70 i+If no Err bitreich.org 70 i+.Ar repo Err bitreich.org 70 i+is specified, then the current directory Err bitreich.org 70 i+is assumed to be the repository. Err bitreich.org 70 i+.Sh OPTIONS Err bitreich.org 70 i+.Bl -tag -width "-v" Err bitreich.org 70 i+.It Fl v Err bitreich.org 70 i+Enable verbose mode. Err bitreich.org 70 i+.El Err bitreich.org 70 i+.Sh AUTHORS Err bitreich.org 70 i+.An Dimitris Papastamos Aq Mt sin@2f30.org , Err bitreich.org 70 i+.An z3bra Aq Mt contactatz3bradotorg . Err bitreich.org 70 1diff --git a/dlist.c b/dlist.c /scm/dedup/file/dlist.c.gph bitreich.org 70 i@@ -0,0 +1,232 @@ Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+#include "arg.h" Err bitreich.org 70 i+#include "blake2.h" Err bitreich.org 70 i+#include "dedup.h" Err bitreich.org 70 i+ Err bitreich.org 70 i+#define SNAPSF ".snapshots" Err bitreich.org 70 i+#define STOREF ".store" Err bitreich.org 70 i+ Err bitreich.org 70 i+enum { Err bitreich.org 70 i+ WALK_CONTINUE, Err bitreich.org 70 i+ WALK_STOP Err bitreich.org 70 i+}; Err bitreich.org 70 i+ Err bitreich.org 70 i+static struct snap_hdr snap_hdr; Err bitreich.org 70 i+static struct blk_hdr blk_hdr; Err bitreich.org 70 i+static int ifd; Err bitreich.org 70 i+static int sfd; Err bitreich.org 70 i+static int hash_algo = HASH_BLAKE2B; Err bitreich.org 70 i+static int compr_algo = COMPR_LZ4; Err bitreich.org 70 i+ Err bitreich.org 70 i+int verbose; Err bitreich.org 70 i+char *argv0; Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+print_md(FILE *fp, uint8_t *md, size_t size) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ size_t i; Err bitreich.org 70 i+ Err bitreich.org 70 i+ for (i = 0; i < size; i++) Err bitreich.org 70 i+ fprintf(fp, "%02x", md[i]); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static struct snap * Err bitreich.org 70 i+alloc_snap(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct snap *snap; Err bitreich.org 70 i+ Err bitreich.org 70 i+ snap = calloc(1, sizeof(*snap)); Err bitreich.org 70 i+ if (snap == NULL) Err bitreich.org 70 i+ err(1, "%s", __func__); Err bitreich.org 70 i+ return snap; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+free_snap(struct snap *snap) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ free(snap); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static struct snap * Err bitreich.org 70 i+grow_snap(struct snap *snap, uint64_t nr_blk_descs) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ size_t size; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (nr_blk_descs > SIZE_MAX / sizeof(snap->blk_desc[0])) Err bitreich.org 70 i+ errx(1, "%s: overflow", __func__); Err bitreich.org 70 i+ size = nr_blk_descs * sizeof(snap->blk_desc[0]); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (size > SIZE_MAX - sizeof(*snap)) Err bitreich.org 70 i+ errx(1, "%s: overflow", __func__); Err bitreich.org 70 i+ size += sizeof(*snap); Err bitreich.org 70 i+ Err bitreich.org 70 i+ snap = realloc(snap, size); Err bitreich.org 70 i+ if (snap == NULL) Err bitreich.org 70 i+ err(1, "%s", __func__); Err bitreich.org 70 i+ return snap; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static int Err bitreich.org 70 i+list(struct snap *snap, void *arg) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ print_md(stdout, snap->md, sizeof(snap->md)); Err bitreich.org 70 i+ if (snap->msg[0] != '\0') Err bitreich.org 70 i+ printf("\t%s\n", snap->msg); Err bitreich.org 70 i+ else Err bitreich.org 70 i+ putchar('\n'); Err bitreich.org 70 i+ return WALK_CONTINUE; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+/* Walk through all snapshots and call fn() on each one */ Err bitreich.org 70 i+static void Err bitreich.org 70 i+walk_snap(int (*fn)(struct snap *, void *), void *arg) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ uint64_t i; Err bitreich.org 70 i+ Err bitreich.org 70 i+ xlseek(ifd, SNAP_HDR_SIZE, SEEK_SET); Err bitreich.org 70 i+ for (i = 0; i < snap_hdr.nr_snaps; i++) { Err bitreich.org 70 i+ struct snap *snap; Err bitreich.org 70 i+ int ret; Err bitreich.org 70 i+ Err bitreich.org 70 i+ snap = alloc_snap(); Err bitreich.org 70 i+ read_snap(ifd, snap); Err bitreich.org 70 i+ snap = grow_snap(snap, snap->nr_blk_descs); Err bitreich.org 70 i+ read_snap_descs(ifd, snap); Err bitreich.org 70 i+ Err bitreich.org 70 i+ ret = (*fn)(snap, arg); Err bitreich.org 70 i+ free_snap(snap); Err bitreich.org 70 i+ if (ret == WALK_STOP) Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ } Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+match_ver(uint64_t v) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ uint8_t maj, min; Err bitreich.org 70 i+ Err bitreich.org 70 i+ min = v & VER_MIN_MASK; Err bitreich.org 70 i+ maj = (v >> VER_MAJ_SHIFT) & VER_MAJ_MASK; Err bitreich.org 70 i+ if (maj == VER_MAJ && min == VER_MIN) Err bitreich.org 70 i+ return; Err bitreich.org 70 i+ errx(1, "format version mismatch: expected %u.%u but got %u.%u", Err bitreich.org 70 i+ VER_MAJ, VER_MIN, maj, min); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+load_blk_hdr(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ uint64_t v; Err bitreich.org 70 i+ Err bitreich.org 70 i+ xlseek(sfd, 0, SEEK_SET); Err bitreich.org 70 i+ read_blk_hdr(sfd, &blk_hdr); Err bitreich.org 70 i+ match_ver(blk_hdr.flags); Err bitreich.org 70 i+ Err bitreich.org 70 i+ v = blk_hdr.flags >> COMPR_ALGO_SHIFT; Err bitreich.org 70 i+ v &= COMPR_ALGO_MASK; Err bitreich.org 70 i+ compr_algo = v; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (compr_algo < 0 || compr_algo >= NR_COMPRS) Err bitreich.org 70 i+ errx(1, "unsupported compression algorithm: %d", compr_algo); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (verbose > 0) Err bitreich.org 70 i+ fprintf(stderr, "Compression algorithm: %s\n", Err bitreich.org 70 i+ compr_type2name(compr_algo)); Err bitreich.org 70 i+ Err bitreich.org 70 i+ v = blk_hdr.flags >> HASH_ALGO_SHIFT; Err bitreich.org 70 i+ v &= HASH_ALGO_MASK; Err bitreich.org 70 i+ hash_algo = v; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (hash_algo < 0 || hash_algo >= NR_HASHES) Err bitreich.org 70 i+ errx(1, "unsupported hash algorithm: %d", hash_algo); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (verbose > 0) Err bitreich.org 70 i+ fprintf(stderr, "Hash algorithm: %s\n", Err bitreich.org 70 i+ hash_type2name(hash_algo)); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+load_snap_hdr(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ xlseek(ifd, 0, SEEK_SET); Err bitreich.org 70 i+ read_snap_hdr(ifd, &snap_hdr); Err bitreich.org 70 i+ match_ver(snap_hdr.flags); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+init(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ ifd = open(SNAPSF, O_RDONLY, 0600); Err bitreich.org 70 i+ if (ifd < 0) Err bitreich.org 70 i+ err(1, "open %s", SNAPSF); Err bitreich.org 70 i+ Err bitreich.org 70 i+ sfd = open(STOREF, O_RDONLY, 0600); Err bitreich.org 70 i+ if (sfd < 0) Err bitreich.org 70 i+ err(1, "open %s", STOREF); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (flock(ifd, LOCK_NB | LOCK_EX) < 0 || Err bitreich.org 70 i+ flock(sfd, LOCK_NB | LOCK_EX) < 0) Err bitreich.org 70 i+ err(1, "flock"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ load_snap_hdr(); Err bitreich.org 70 i+ load_blk_hdr(); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+term(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ close(sfd); Err bitreich.org 70 i+ close(ifd); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+usage(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ fprintf(stderr, "usage: %s [-v] [repo]\n", argv0); Err bitreich.org 70 i+ exit(1); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+main(int argc, char *argv[]) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ char *repo = NULL; Err bitreich.org 70 i+ Err bitreich.org 70 i+ ARGBEGIN { Err bitreich.org 70 i+ case 'v': Err bitreich.org 70 i+ verbose++; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ default: Err bitreich.org 70 i+ usage(); Err bitreich.org 70 i+ } ARGEND Err bitreich.org 70 i+ Err bitreich.org 70 i+ switch (argc) { Err bitreich.org 70 i+ case 0: Err bitreich.org 70 i+ repo = "."; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case 1: Err bitreich.org 70 i+ repo = argv[0]; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ default: Err bitreich.org 70 i+ usage(); Err bitreich.org 70 i+ }; Err bitreich.org 70 i+ Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (chdir(repo) < 0) Err bitreich.org 70 i+ err(1, "chdir: %s", repo); Err bitreich.org 70 i+ Err bitreich.org 70 i+ init(); Err bitreich.org 70 i+ walk_snap(list, NULL); Err bitreich.org 70 i+ term(); Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 1diff --git a/dpack.1 b/dpack.1 /scm/dedup/file/dpack.1.gph bitreich.org 70 i@@ -0,0 +1,35 @@ Err bitreich.org 70 i+.Dd April 17, 2019 Err bitreich.org 70 i+.Dt DPACK 1 Err bitreich.org 70 i+.Os Err bitreich.org 70 i+.Sh NAME Err bitreich.org 70 i+.Nm dpack Err bitreich.org 70 i+.Nd Deduplicate data from stdin Err bitreich.org 70 i+.Sh SYNOPSIS Err bitreich.org 70 i+.Nm dpack Err bitreich.org 70 i+.Op Fl v Err bitreich.org 70 i+.Op Fl m Ar message Err bitreich.org 70 i+.Op repo Err bitreich.org 70 i+.Sh DESCRIPTION Err bitreich.org 70 i+.Nm Err bitreich.org 70 i+deduplicates data from stdin. Err bitreich.org 70 i+If no Err bitreich.org 70 i+.Ar repo Err bitreich.org 70 i+is specified, then the current directory Err bitreich.org 70 i+is assumed to be the repository. Err bitreich.org 70 i+.Pp Err bitreich.org 70 i+.Nm Err bitreich.org 70 i+does not track any file metadata so to deduplicate Err bitreich.org 70 i+directory trees, an archival tool like Err bitreich.org 70 i+.Xr tar 1 Err bitreich.org 70 i+should be used and piped into Err bitreich.org 70 i+.Nm . Err bitreich.org 70 i+.Sh OPTIONS Err bitreich.org 70 i+.Bl -tag -width "-m message" Err bitreich.org 70 i+.It Fl m Ar message Err bitreich.org 70 i+Attach a descriptive message to the snapshot. Err bitreich.org 70 i+.It Fl v Err bitreich.org 70 i+Enable verbose mode. Err bitreich.org 70 i+.El Err bitreich.org 70 i+.Sh AUTHORS Err bitreich.org 70 i+.An Dimitris Papastamos Aq Mt sin@2f30.org , Err bitreich.org 70 i+.An z3bra Aq Mt contactatz3bradotorg . Err bitreich.org 70 1diff --git a/dpack.c b/dpack.c /scm/dedup/file/dpack.c.gph bitreich.org 70 i@@ -0,0 +1,422 @@ Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+#include "arg.h" Err bitreich.org 70 i+#include "blake2.h" Err bitreich.org 70 i+#include "dedup.h" Err bitreich.org 70 i+ Err bitreich.org 70 i+#define SNAPSF ".snapshots" Err bitreich.org 70 i+#define STOREF ".store" Err bitreich.org 70 i+ Err bitreich.org 70 i+enum { Err bitreich.org 70 i+ WALK_CONTINUE, Err bitreich.org 70 i+ WALK_STOP Err bitreich.org 70 i+}; Err bitreich.org 70 i+ Err bitreich.org 70 i+static struct snap_hdr snap_hdr; Err bitreich.org 70 i+static struct blk_hdr blk_hdr; Err bitreich.org 70 i+static struct icache *icache; Err bitreich.org 70 i+static int ifd; Err bitreich.org 70 i+static int sfd; Err bitreich.org 70 i+static int hash_algo = HASH_BLAKE2B; Err bitreich.org 70 i+static int compr_algo = COMPR_LZ4; Err bitreich.org 70 i+ Err bitreich.org 70 i+int verbose; Err bitreich.org 70 i+char *argv0; Err bitreich.org 70 i+ Err bitreich.org 70 i+static struct snap * Err bitreich.org 70 i+alloc_snap(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct snap *snap; Err bitreich.org 70 i+ Err bitreich.org 70 i+ snap = calloc(1, sizeof(*snap)); Err bitreich.org 70 i+ if (snap == NULL) Err bitreich.org 70 i+ err(1, "%s", __func__); Err bitreich.org 70 i+ return snap; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+free_snap(struct snap *snap) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ free(snap); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+/* Err bitreich.org 70 i+ * The snapshot hash is calculated over the Err bitreich.org 70 i+ * hash of its block descriptors. Err bitreich.org 70 i+ */ Err bitreich.org 70 i+static void Err bitreich.org 70 i+hash_snap(struct snap *snap, uint8_t *md) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct hash_ctx ctx; Err bitreich.org 70 i+ uint64_t i; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (hash_init(&ctx, hash_algo, MD_SIZE) < 0) Err bitreich.org 70 i+ errx(1, "hash_init failed"); Err bitreich.org 70 i+ for (i = 0; i < snap->nr_blk_descs; i++) { Err bitreich.org 70 i+ struct blk_desc *blk_desc; Err bitreich.org 70 i+ Err bitreich.org 70 i+ blk_desc = &snap->blk_desc[i]; Err bitreich.org 70 i+ hash_update(&ctx, blk_desc->md, sizeof(blk_desc->md)); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ hash_final(&ctx, md, MD_SIZE); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static struct snap * Err bitreich.org 70 i+grow_snap(struct snap *snap, uint64_t nr_blk_descs) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ size_t size; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (nr_blk_descs > SIZE_MAX / sizeof(snap->blk_desc[0])) Err bitreich.org 70 i+ errx(1, "%s: overflow", __func__); Err bitreich.org 70 i+ size = nr_blk_descs * sizeof(snap->blk_desc[0]); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (size > SIZE_MAX - sizeof(*snap)) Err bitreich.org 70 i+ errx(1, "%s: overflow", __func__); Err bitreich.org 70 i+ size += sizeof(*snap); Err bitreich.org 70 i+ Err bitreich.org 70 i+ snap = realloc(snap, size); Err bitreich.org 70 i+ if (snap == NULL) Err bitreich.org 70 i+ err(1, "%s", __func__); Err bitreich.org 70 i+ return snap; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+append_snap(struct snap *snap) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ if (snap->nr_blk_descs > UINT64_MAX / BLK_DESC_SIZE) Err bitreich.org 70 i+ errx(1, "%s: overflow", __func__); Err bitreich.org 70 i+ snap->size = snap->nr_blk_descs * BLK_DESC_SIZE; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (snap->size > UINT64_MAX - SNAPSHOT_SIZE) Err bitreich.org 70 i+ errx(1, "%s: overflow", __func__); Err bitreich.org 70 i+ snap->size += SNAPSHOT_SIZE; Err bitreich.org 70 i+ Err bitreich.org 70 i+ xlseek(ifd, snap_hdr.size, SEEK_SET); Err bitreich.org 70 i+ write_snap(ifd, snap); Err bitreich.org 70 i+ write_snap_blk_descs(ifd, snap); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (snap_hdr.size > UINT64_MAX - snap->size) Err bitreich.org 70 i+ errx(1, "%s: overflow", __func__); Err bitreich.org 70 i+ snap_hdr.size += snap->size; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (snap_hdr.nr_snaps > UINT64_MAX - 1) Err bitreich.org 70 i+ errx(1, "%s: overflow", __func__); Err bitreich.org 70 i+ snap_hdr.nr_snaps++; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static uint8_t * Err bitreich.org 70 i+alloc_buf(size_t size) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ void *p; Err bitreich.org 70 i+ Err bitreich.org 70 i+ p = calloc(1, size); Err bitreich.org 70 i+ if (p == NULL) Err bitreich.org 70 i+ err(1, "%s", __func__); Err bitreich.org 70 i+ return p; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+hash_blk(uint8_t *buf, size_t size, uint8_t *md) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct hash_ctx ctx; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (hash_init(&ctx, hash_algo, MD_SIZE) < 0) Err bitreich.org 70 i+ errx(1, "hash_init failed"); Err bitreich.org 70 i+ hash_update(&ctx, buf, size); Err bitreich.org 70 i+ hash_final(&ctx, md, MD_SIZE); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+append_blk(uint8_t *buf, struct blk_desc *blk_desc) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ xlseek(sfd, blk_hdr.size, SEEK_SET); Err bitreich.org 70 i+ xwrite(sfd, buf, blk_desc->size); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (blk_hdr.size > UINT64_MAX - blk_desc->size) Err bitreich.org 70 i+ errx(1, "%s: overflow", __func__); Err bitreich.org 70 i+ blk_hdr.size += blk_desc->size; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+dedup_chunk(struct snap *snap, uint8_t *chunkp, size_t chunk_size) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ uint8_t md[MD_SIZE]; Err bitreich.org 70 i+ struct blk_desc blk_desc; Err bitreich.org 70 i+ struct compr_ctx ctx; Err bitreich.org 70 i+ uint8_t *compr_buf; Err bitreich.org 70 i+ size_t n, csize; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (compr_init(&ctx, compr_algo) < 0) Err bitreich.org 70 i+ errx(1, "compr_init failed"); Err bitreich.org 70 i+ csize = compr_size(&ctx, BLKSIZE_MAX); Err bitreich.org 70 i+ compr_buf = alloc_buf(csize); Err bitreich.org 70 i+ Err bitreich.org 70 i+ n = compr(&ctx, chunkp, compr_buf, chunk_size, csize); Err bitreich.org 70 i+ hash_blk(compr_buf, n, md); Err bitreich.org 70 i+ Err bitreich.org 70 i+ snap_hdr.st.orig_size += chunk_size; Err bitreich.org 70 i+ snap_hdr.st.compr_size += n; Err bitreich.org 70 i+ Err bitreich.org 70 i+ memcpy(blk_desc.md, md, sizeof(blk_desc.md)); Err bitreich.org 70 i+ if (lookup_icache(icache, &blk_desc) < 0) { Err bitreich.org 70 i+ blk_desc.offset = blk_hdr.size; Err bitreich.org 70 i+ blk_desc.size = n; Err bitreich.org 70 i+ Err bitreich.org 70 i+ snap->blk_desc[snap->nr_blk_descs++] = blk_desc; Err bitreich.org 70 i+ append_blk(compr_buf, &blk_desc); Err bitreich.org 70 i+ Err bitreich.org 70 i+ insert_icache(icache, &blk_desc); Err bitreich.org 70 i+ Err bitreich.org 70 i+ snap_hdr.st.dedup_size += blk_desc.size; Err bitreich.org 70 i+ snap_hdr.st.nr_blks++; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (blk_desc.size > snap_hdr.st.max_blk_size) Err bitreich.org 70 i+ snap_hdr.st.max_blk_size = blk_desc.size; Err bitreich.org 70 i+ if (blk_desc.size < snap_hdr.st.min_blk_size) Err bitreich.org 70 i+ snap_hdr.st.min_blk_size = blk_desc.size; Err bitreich.org 70 i+ } else { Err bitreich.org 70 i+ snap->blk_desc[snap->nr_blk_descs++] = blk_desc; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ free(compr_buf); Err bitreich.org 70 i+ compr_final(&ctx); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+dedup(int fd, char *msg) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct snap *snap; Err bitreich.org 70 i+ struct chunker *chunker; Err bitreich.org 70 i+ Err bitreich.org 70 i+ snap = alloc_snap(); Err bitreich.org 70 i+ chunker = alloc_chunker(fd, BLKSIZE_MIN, BLKSIZE_MAX, Err bitreich.org 70 i+ HASHMASK_BITS, WINSIZE); Err bitreich.org 70 i+ Err bitreich.org 70 i+ while (fill_chunker(chunker) > 0) { Err bitreich.org 70 i+ uint8_t *chunkp; Err bitreich.org 70 i+ size_t chunk_size; Err bitreich.org 70 i+ Err bitreich.org 70 i+ chunkp = get_chunk(chunker, &chunk_size); Err bitreich.org 70 i+ snap = grow_snap(snap, snap->nr_blk_descs + 1); Err bitreich.org 70 i+ dedup_chunk(snap, chunkp, chunk_size); Err bitreich.org 70 i+ drain_chunker(chunker); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (snap->nr_blk_descs > 0) { Err bitreich.org 70 i+ if (msg != NULL) { Err bitreich.org 70 i+ size_t size; Err bitreich.org 70 i+ Err bitreich.org 70 i+ size = strlen(msg) + 1; Err bitreich.org 70 i+ if (size > sizeof(snap->msg)) Err bitreich.org 70 i+ size = sizeof(snap->msg); Err bitreich.org 70 i+ memcpy(snap->msg, msg, size); Err bitreich.org 70 i+ snap->msg[size - 1] = '\0'; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ hash_snap(snap, snap->md); Err bitreich.org 70 i+ append_snap(snap); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ free_chunker(chunker); Err bitreich.org 70 i+ free_snap(snap); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static int Err bitreich.org 70 i+build_icache(struct snap *snap, void *arg) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct compr_ctx ctx; Err bitreich.org 70 i+ uint8_t *buf; Err bitreich.org 70 i+ uint64_t i; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (compr_init(&ctx, compr_algo) < 0) Err bitreich.org 70 i+ errx(1, "compr_init failed"); Err bitreich.org 70 i+ buf = alloc_buf(compr_size(&ctx, BLKSIZE_MAX)); Err bitreich.org 70 i+ for (i = 0; i < snap->nr_blk_descs; i++) { Err bitreich.org 70 i+ struct blk_desc *blk_desc; Err bitreich.org 70 i+ Err bitreich.org 70 i+ blk_desc = &snap->blk_desc[i]; Err bitreich.org 70 i+ insert_icache(icache, blk_desc); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ free(buf); Err bitreich.org 70 i+ compr_final(&ctx); Err bitreich.org 70 i+ return WALK_CONTINUE; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+/* Walk through all snapshots and call fn() on each one */ Err bitreich.org 70 i+static void Err bitreich.org 70 i+walk_snap(int (*fn)(struct snap *, void *), void *arg) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ uint64_t i; Err bitreich.org 70 i+ Err bitreich.org 70 i+ xlseek(ifd, SNAP_HDR_SIZE, SEEK_SET); Err bitreich.org 70 i+ for (i = 0; i < snap_hdr.nr_snaps; i++) { Err bitreich.org 70 i+ struct snap *snap; Err bitreich.org 70 i+ int ret; Err bitreich.org 70 i+ Err bitreich.org 70 i+ snap = alloc_snap(); Err bitreich.org 70 i+ read_snap(ifd, snap); Err bitreich.org 70 i+ snap = grow_snap(snap, snap->nr_blk_descs); Err bitreich.org 70 i+ read_snap_descs(ifd, snap); Err bitreich.org 70 i+ Err bitreich.org 70 i+ ret = (*fn)(snap, arg); Err bitreich.org 70 i+ free_snap(snap); Err bitreich.org 70 i+ if (ret == WALK_STOP) Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ } Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+match_ver(uint64_t v) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ uint8_t maj, min; Err bitreich.org 70 i+ Err bitreich.org 70 i+ min = v & VER_MIN_MASK; Err bitreich.org 70 i+ maj = (v >> VER_MAJ_SHIFT) & VER_MAJ_MASK; Err bitreich.org 70 i+ if (maj == VER_MAJ && min == VER_MIN) Err bitreich.org 70 i+ return; Err bitreich.org 70 i+ errx(1, "format version mismatch: expected %u.%u but got %u.%u", Err bitreich.org 70 i+ VER_MAJ, VER_MIN, maj, min); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+load_blk_hdr(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ uint64_t v; Err bitreich.org 70 i+ Err bitreich.org 70 i+ xlseek(sfd, 0, SEEK_SET); Err bitreich.org 70 i+ read_blk_hdr(sfd, &blk_hdr); Err bitreich.org 70 i+ match_ver(blk_hdr.flags); Err bitreich.org 70 i+ Err bitreich.org 70 i+ v = blk_hdr.flags >> COMPR_ALGO_SHIFT; Err bitreich.org 70 i+ v &= COMPR_ALGO_MASK; Err bitreich.org 70 i+ compr_algo = v; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (compr_algo < 0 || compr_algo >= NR_COMPRS) Err bitreich.org 70 i+ errx(1, "unsupported compression algorithm: %d", compr_algo); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (verbose > 0) Err bitreich.org 70 i+ fprintf(stderr, "Compression algorithm: %s\n", Err bitreich.org 70 i+ compr_type2name(compr_algo)); Err bitreich.org 70 i+ Err bitreich.org 70 i+ v = blk_hdr.flags >> HASH_ALGO_SHIFT; Err bitreich.org 70 i+ v &= HASH_ALGO_MASK; Err bitreich.org 70 i+ hash_algo = v; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (hash_algo < 0 || hash_algo >= NR_HASHES) Err bitreich.org 70 i+ errx(1, "unsupported hash algorithm: %d", hash_algo); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (verbose > 0) Err bitreich.org 70 i+ fprintf(stderr, "Hash algorithm: %s\n", Err bitreich.org 70 i+ hash_type2name(hash_algo)); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+save_blk_hdr(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ xlseek(sfd, 0, SEEK_SET); Err bitreich.org 70 i+ write_blk_hdr(sfd, &blk_hdr); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+load_snap_hdr(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ xlseek(ifd, 0, SEEK_SET); Err bitreich.org 70 i+ read_snap_hdr(ifd, &snap_hdr); Err bitreich.org 70 i+ match_ver(snap_hdr.flags); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+save_snap_hdr(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ xlseek(ifd, 0, SEEK_SET); Err bitreich.org 70 i+ write_snap_hdr(ifd, &snap_hdr); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+init(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ ifd = open(SNAPSF, O_RDWR, 0600); Err bitreich.org 70 i+ if (ifd < 0) Err bitreich.org 70 i+ err(1, "open %s", SNAPSF); Err bitreich.org 70 i+ Err bitreich.org 70 i+ sfd = open(STOREF, O_RDWR, 0600); Err bitreich.org 70 i+ if (sfd < 0) Err bitreich.org 70 i+ err(1, "open %s", STOREF); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (flock(ifd, LOCK_NB | LOCK_EX) < 0 || Err bitreich.org 70 i+ flock(sfd, LOCK_NB | LOCK_EX) < 0) Err bitreich.org 70 i+ err(1, "flock"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ load_snap_hdr(); Err bitreich.org 70 i+ load_blk_hdr(); Err bitreich.org 70 i+ Err bitreich.org 70 i+ icache = alloc_icache(); Err bitreich.org 70 i+ walk_snap(build_icache, NULL); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+term(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ free_icache(icache); Err bitreich.org 70 i+ Err bitreich.org 70 i+ save_blk_hdr(); Err bitreich.org 70 i+ save_snap_hdr(); Err bitreich.org 70 i+ Err bitreich.org 70 i+ fsync(sfd); Err bitreich.org 70 i+ fsync(ifd); Err bitreich.org 70 i+ Err bitreich.org 70 i+ close(sfd); Err bitreich.org 70 i+ close(ifd); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+usage(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ fprintf(stderr, "usage: %s [-v] [-m message] [repo]\n", argv0); Err bitreich.org 70 i+ exit(1); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+main(int argc, char *argv[]) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ char *repo, *msg = NULL; Err bitreich.org 70 i+ Err bitreich.org 70 i+ ARGBEGIN { Err bitreich.org 70 i+ case 'm': Err bitreich.org 70 i+ msg = EARGF(usage()); Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case 'v': Err bitreich.org 70 i+ verbose++; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ default: Err bitreich.org 70 i+ usage(); Err bitreich.org 70 i+ } ARGEND Err bitreich.org 70 i+ Err bitreich.org 70 i+ switch (argc) { Err bitreich.org 70 i+ case 0: Err bitreich.org 70 i+ repo = "."; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case 1: Err bitreich.org 70 i+ repo = argv[0]; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ default: Err bitreich.org 70 i+ usage(); Err bitreich.org 70 i+ }; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (chdir(repo) < 0) Err bitreich.org 70 i+ err(1, "chdir: %s", repo); Err bitreich.org 70 i+ Err bitreich.org 70 i+ init(); Err bitreich.org 70 i+ dedup(STDIN_FILENO, msg); Err bitreich.org 70 i+ term(); Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 1diff --git a/dunpack.1 b/dunpack.1 /scm/dedup/file/dunpack.1.gph bitreich.org 70 i@@ -0,0 +1,28 @@ Err bitreich.org 70 i+.Dd April 17, 2019 Err bitreich.org 70 i+.Dt DUNPACK 1 Err bitreich.org 70 i+.Os Err bitreich.org 70 i+.Sh NAME Err bitreich.org 70 i+.Nm dunpack Err bitreich.org 70 i+.Nd Extract snapshot from a dedup repository Err bitreich.org 70 i+.Sh SYNOPSIS Err bitreich.org 70 i+.Nm dunpack Err bitreich.org 70 i+.Op Fl v Err bitreich.org 70 i+.Ar id Err bitreich.org 70 i+.Op repo Err bitreich.org 70 i+.Sh DESCRIPTION Err bitreich.org 70 i+.Nm Err bitreich.org 70 i+extracts the snapshot specified by Err bitreich.org 70 i+.Ar id Err bitreich.org 70 i+from the dedup repository. Err bitreich.org 70 i+If no Err bitreich.org 70 i+.Ar repo Err bitreich.org 70 i+is specified, then the current directory Err bitreich.org 70 i+is assumed to be the repository. Err bitreich.org 70 i+.Sh OPTIONS Err bitreich.org 70 i+.Bl -tag -width "-v" Err bitreich.org 70 i+.It Fl v Err bitreich.org 70 i+Enable verbose mode. Err bitreich.org 70 i+.El Err bitreich.org 70 i+.Sh AUTHORS Err bitreich.org 70 i+.An Dimitris Papastamos Aq Mt sin@2f30.org , Err bitreich.org 70 i+.An z3bra Aq Mt contactatz3bradotorg . Err bitreich.org 70 1diff --git a/dunpack.c b/dunpack.c /scm/dedup/file/dunpack.c.gph bitreich.org 70 i@@ -0,0 +1,288 @@ Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+#include Err bitreich.org 70 i+ Err bitreich.org 70 i+#include "arg.h" Err bitreich.org 70 i+#include "blake2.h" Err bitreich.org 70 i+#include "dedup.h" Err bitreich.org 70 i+ Err bitreich.org 70 i+#define SNAPSF ".snapshots" Err bitreich.org 70 i+#define STOREF ".store" Err bitreich.org 70 i+ Err bitreich.org 70 i+enum { Err bitreich.org 70 i+ WALK_CONTINUE, Err bitreich.org 70 i+ WALK_STOP Err bitreich.org 70 i+}; Err bitreich.org 70 i+ Err bitreich.org 70 i+struct extract_args { Err bitreich.org 70 i+ uint8_t *md; Err bitreich.org 70 i+ int fd; Err bitreich.org 70 i+ int ret; Err bitreich.org 70 i+}; Err bitreich.org 70 i+ Err bitreich.org 70 i+static struct snap_hdr snap_hdr; Err bitreich.org 70 i+static struct blk_hdr blk_hdr; Err bitreich.org 70 i+static int ifd; Err bitreich.org 70 i+static int sfd; Err bitreich.org 70 i+static int hash_algo = HASH_BLAKE2B; Err bitreich.org 70 i+static int compr_algo = COMPR_LZ4; Err bitreich.org 70 i+ Err bitreich.org 70 i+int verbose; Err bitreich.org 70 i+char *argv0; Err bitreich.org 70 i+ Err bitreich.org 70 i+static struct snap * Err bitreich.org 70 i+alloc_snap(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct snap *snap; Err bitreich.org 70 i+ Err bitreich.org 70 i+ snap = calloc(1, sizeof(*snap)); Err bitreich.org 70 i+ if (snap == NULL) Err bitreich.org 70 i+ err(1, "%s", __func__); Err bitreich.org 70 i+ return snap; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+free_snap(struct snap *snap) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ free(snap); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static struct snap * Err bitreich.org 70 i+grow_snap(struct snap *snap, uint64_t nr_blk_descs) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ size_t size; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (nr_blk_descs > SIZE_MAX / sizeof(snap->blk_desc[0])) Err bitreich.org 70 i+ errx(1, "%s: overflow", __func__); Err bitreich.org 70 i+ size = nr_blk_descs * sizeof(snap->blk_desc[0]); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (size > SIZE_MAX - sizeof(*snap)) Err bitreich.org 70 i+ errx(1, "%s: overflow", __func__); Err bitreich.org 70 i+ size += sizeof(*snap); Err bitreich.org 70 i+ Err bitreich.org 70 i+ snap = realloc(snap, size); Err bitreich.org 70 i+ if (snap == NULL) Err bitreich.org 70 i+ err(1, "%s", __func__); Err bitreich.org 70 i+ return snap; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static uint8_t * Err bitreich.org 70 i+alloc_buf(size_t size) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ void *p; Err bitreich.org 70 i+ Err bitreich.org 70 i+ p = calloc(1, size); Err bitreich.org 70 i+ if (p == NULL) Err bitreich.org 70 i+ err(1, "%s", __func__); Err bitreich.org 70 i+ return p; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+free_buf(uint8_t *buf) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ free(buf); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+read_blk(uint8_t *buf, struct blk_desc *blk_desc) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ ssize_t n; Err bitreich.org 70 i+ Err bitreich.org 70 i+ xlseek(sfd, blk_desc->offset, SEEK_SET); Err bitreich.org 70 i+ n = xread(sfd, buf, blk_desc->size); Err bitreich.org 70 i+ if (n == 0) Err bitreich.org 70 i+ errx(1, "%s: unexpected EOF", __func__); Err bitreich.org 70 i+ if (n != blk_desc->size) Err bitreich.org 70 i+ errx(1, "%s: short read", __func__); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static int Err bitreich.org 70 i+extract(struct snap *snap, void *arg) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ uint8_t *buf[2]; Err bitreich.org 70 i+ struct extract_args *args = arg; Err bitreich.org 70 i+ struct compr_ctx ctx; Err bitreich.org 70 i+ uint64_t i; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (memcmp(snap->md, args->md, sizeof(snap->md)) != 0) Err bitreich.org 70 i+ return WALK_CONTINUE; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (compr_init(&ctx, compr_algo) < 0) Err bitreich.org 70 i+ errx(1, "compr_init failed"); Err bitreich.org 70 i+ buf[0] = alloc_buf(BLKSIZE_MAX); Err bitreich.org 70 i+ buf[1] = alloc_buf(compr_size(&ctx, BLKSIZE_MAX)); Err bitreich.org 70 i+ for (i = 0; i < snap->nr_blk_descs; i++) { Err bitreich.org 70 i+ struct blk_desc *blk_desc; Err bitreich.org 70 i+ size_t blksize; Err bitreich.org 70 i+ Err bitreich.org 70 i+ blk_desc = &snap->blk_desc[i]; Err bitreich.org 70 i+ read_blk(buf[1], blk_desc); Err bitreich.org 70 i+ blksize = decompr(&ctx, buf[1], buf[0], blk_desc->size, BLKSIZE_MAX); Err bitreich.org 70 i+ xwrite(args->fd, buf[0], blksize); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ free_buf(buf[1]); Err bitreich.org 70 i+ free_buf(buf[0]); Err bitreich.org 70 i+ compr_final(&ctx); Err bitreich.org 70 i+ args->ret = 0; Err bitreich.org 70 i+ return WALK_STOP; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+/* Walk through all snapshots and call fn() on each one */ Err bitreich.org 70 i+static void Err bitreich.org 70 i+walk_snap(int (*fn)(struct snap *, void *), void *arg) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ uint64_t i; Err bitreich.org 70 i+ Err bitreich.org 70 i+ xlseek(ifd, SNAP_HDR_SIZE, SEEK_SET); Err bitreich.org 70 i+ for (i = 0; i < snap_hdr.nr_snaps; i++) { Err bitreich.org 70 i+ struct snap *snap; Err bitreich.org 70 i+ int ret; Err bitreich.org 70 i+ Err bitreich.org 70 i+ snap = alloc_snap(); Err bitreich.org 70 i+ read_snap(ifd, snap); Err bitreich.org 70 i+ snap = grow_snap(snap, snap->nr_blk_descs); Err bitreich.org 70 i+ read_snap_descs(ifd, snap); Err bitreich.org 70 i+ Err bitreich.org 70 i+ ret = (*fn)(snap, arg); Err bitreich.org 70 i+ free_snap(snap); Err bitreich.org 70 i+ if (ret == WALK_STOP) Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ } Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+match_ver(uint64_t v) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ uint8_t maj, min; Err bitreich.org 70 i+ Err bitreich.org 70 i+ min = v & VER_MIN_MASK; Err bitreich.org 70 i+ maj = (v >> VER_MAJ_SHIFT) & VER_MAJ_MASK; Err bitreich.org 70 i+ if (maj == VER_MAJ && min == VER_MIN) Err bitreich.org 70 i+ return; Err bitreich.org 70 i+ errx(1, "format version mismatch: expected %u.%u but got %u.%u", Err bitreich.org 70 i+ VER_MAJ, VER_MIN, maj, min); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+load_blk_hdr(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ uint64_t v; Err bitreich.org 70 i+ Err bitreich.org 70 i+ xlseek(sfd, 0, SEEK_SET); Err bitreich.org 70 i+ read_blk_hdr(sfd, &blk_hdr); Err bitreich.org 70 i+ match_ver(blk_hdr.flags); Err bitreich.org 70 i+ Err bitreich.org 70 i+ v = blk_hdr.flags >> COMPR_ALGO_SHIFT; Err bitreich.org 70 i+ v &= COMPR_ALGO_MASK; Err bitreich.org 70 i+ compr_algo = v; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (compr_algo < 0 || compr_algo >= NR_COMPRS) Err bitreich.org 70 i+ errx(1, "unsupported compression algorithm: %d", compr_algo); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (verbose > 0) Err bitreich.org 70 i+ fprintf(stderr, "Compression algorithm: %s\n", Err bitreich.org 70 i+ compr_type2name(compr_algo)); Err bitreich.org 70 i+ Err bitreich.org 70 i+ v = blk_hdr.flags >> HASH_ALGO_SHIFT; Err bitreich.org 70 i+ v &= HASH_ALGO_MASK; Err bitreich.org 70 i+ hash_algo = v; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (hash_algo < 0 || hash_algo >= NR_HASHES) Err bitreich.org 70 i+ errx(1, "unsupported hash algorithm: %d", hash_algo); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (verbose > 0) Err bitreich.org 70 i+ fprintf(stderr, "Hash algorithm: %s\n", Err bitreich.org 70 i+ hash_type2name(hash_algo)); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+load_snap_hdr(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ xlseek(ifd, 0, SEEK_SET); Err bitreich.org 70 i+ read_snap_hdr(ifd, &snap_hdr); Err bitreich.org 70 i+ match_ver(snap_hdr.flags); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+init(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ ifd = open(SNAPSF, O_RDONLY, 0600); Err bitreich.org 70 i+ if (ifd < 0) Err bitreich.org 70 i+ err(1, "open %s", SNAPSF); Err bitreich.org 70 i+ Err bitreich.org 70 i+ sfd = open(STOREF, O_RDONLY, 0600); Err bitreich.org 70 i+ if (sfd < 0) Err bitreich.org 70 i+ err(1, "open %s", STOREF); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (flock(ifd, LOCK_NB | LOCK_EX) < 0 || Err bitreich.org 70 i+ flock(sfd, LOCK_NB | LOCK_EX) < 0) Err bitreich.org 70 i+ err(1, "flock"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ load_snap_hdr(); Err bitreich.org 70 i+ load_blk_hdr(); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+term(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ close(sfd); Err bitreich.org 70 i+ close(ifd); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static void Err bitreich.org 70 i+usage(void) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ fprintf(stderr, "usage: %s [-v] id [repo]\n", argv0); Err bitreich.org 70 i+ exit(1); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+main(int argc, char *argv[]) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ uint8_t md[MD_SIZE]; Err bitreich.org 70 i+ char *repo, *id = NULL; Err bitreich.org 70 i+ struct extract_args args; Err bitreich.org 70 i+ Err bitreich.org 70 i+ ARGBEGIN { Err bitreich.org 70 i+ case 'v': Err bitreich.org 70 i+ verbose++; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ default: Err bitreich.org 70 i+ usage(); Err bitreich.org 70 i+ } ARGEND Err bitreich.org 70 i+ Err bitreich.org 70 i+ switch (argc) { Err bitreich.org 70 i+ case 1: Err bitreich.org 70 i+ id = argv[0]; Err bitreich.org 70 i+ repo = "."; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ case 2: Err bitreich.org 70 i+ id = argv[0]; Err bitreich.org 70 i+ repo = argv[1]; Err bitreich.org 70 i+ break; Err bitreich.org 70 i+ default: Err bitreich.org 70 i+ usage(); Err bitreich.org 70 i+ }; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (chdir(repo) < 0) Err bitreich.org 70 i+ err(1, "chdir: %s", repo); Err bitreich.org 70 i+ Err bitreich.org 70 i+ init(); Err bitreich.org 70 i+ str2bin(id, md); Err bitreich.org 70 i+ args.md = md; Err bitreich.org 70 i+ args.fd = STDIN_FILENO; Err bitreich.org 70 i+ args.ret = -1; Err bitreich.org 70 i+ walk_snap(extract, &args); Err bitreich.org 70 i+ if (args.ret != 0) Err bitreich.org 70 i+ errx(1, "unknown snapshot: %s", id); Err bitreich.org 70 i+ term(); Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 .