iImplement dup-check(1) - 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 3205dbd75458fc84e08ca98ee1e1fe17b19f2693 /scm/dedup/commit/3205dbd75458fc84e08ca98ee1e1fe17b19f2693.gph bitreich.org 70 1parent 2d0701e96dd5242eefe456dca44a5c2b8ba67eb5 /scm/dedup/commit/2d0701e96dd5242eefe456dca44a5c2b8ba67eb5.gph bitreich.org 70 hAuthor: sin URL:mailto:sin@2f30.org bitreich.org 70 iDate: Thu, 25 Apr 2019 20:54:30 +0100 Err bitreich.org 70 i Err bitreich.org 70 iImplement dup-check(1) Err bitreich.org 70 i Err bitreich.org 70 iDiffstat: Err bitreich.org 70 i M Makefile | 12 ++++++++---- Err bitreich.org 70 i M TODO | 1 - Err bitreich.org 70 i M bcompress.c | 11 +++++++++++ Err bitreich.org 70 i M block.c | 12 ++++++++++++ Err bitreich.org 70 i M block.h | 2 ++ Err bitreich.org 70 i M bstorage.c | 49 +++++++++++++++++++++++++++++++ Err bitreich.org 70 i M dotest | 4 ++++ Err bitreich.org 70 i A dup-check.1 | 25 +++++++++++++++++++++++++ Err bitreich.org 70 i A dup-check.c | 81 ++++++++++++++++++++++++++++++ Err bitreich.org 70 i Err bitreich.org 70 i9 files changed, 192 insertions(+), 5 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@@ -1,7 +1,7 @@ Err bitreich.org 70 i include config.mk Err bitreich.org 70 i Err bitreich.org 70 i-BIN = dup-init dup-pack dup-unpack Err bitreich.org 70 i-MAN = dup-init.1 dup-pack.1 dup-unpack.1 Err bitreich.org 70 i+BIN = dup-check dup-init dup-pack dup-unpack Err bitreich.org 70 i+MAN = dup-check.1 dup-init.1 dup-pack.1 dup-unpack.1 Err bitreich.org 70 i Err bitreich.org 70 i HDR = \ Err bitreich.org 70 i arg.h \ Err bitreich.org 70 i@@ -24,6 +24,7 @@ COMMOBJ = \ Err bitreich.org 70 i snap.o \ Err bitreich.org 70 i unpack.o \ Err bitreich.org 70 i Err bitreich.org 70 i+DCHECKOBJ = $(COMMOBJ) dup-check.o Err bitreich.org 70 i DINITOBJ = $(COMMOBJ) dup-init.o Err bitreich.org 70 i DPACKOBJ = $(COMMOBJ) dup-pack.o Err bitreich.org 70 i DUNPACKOBJ = $(COMMOBJ) dup-unpack.o Err bitreich.org 70 i@@ -32,10 +33,10 @@ LDLIBS = -lsnappy Err bitreich.org 70 i Err bitreich.org 70 i all: $(BIN) Err bitreich.org 70 i Err bitreich.org 70 i-$(DINITOBJ) $(DPACKOBJ) $(DUNPACKOBJ): $(HDR) Err bitreich.org 70 i+$(DCHECKOBJ) $(DINITOBJ) $(DPACKOBJ) $(DUNPACKOBJ): $(HDR) Err bitreich.org 70 i Err bitreich.org 70 i clean: Err bitreich.org 70 i- rm -f $(DINITOBJ) $(DPACKOBJ) $(DUNPACKOBJ) $(BIN) Err bitreich.org 70 i+ rm -f $(DCHECKOBJ) $(DINITOBJ) $(DPACKOBJ) $(DUNPACKOBJ) $(BIN) Err bitreich.org 70 i rm -rf dedup-$(VERSION) dedup-$(VERSION).tar.gz Err bitreich.org 70 i Err bitreich.org 70 i install: all Err bitreich.org 70 i@@ -58,6 +59,9 @@ dist: clean 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+dup-check: $(DCHECKOBJ) Err bitreich.org 70 i+ $(CC) -o $@ $(DCHECKOBJ) $(LDFLAGS) $(LDLIBS) Err bitreich.org 70 i+ Err bitreich.org 70 i dup-init: $(DINITOBJ) Err bitreich.org 70 i $(CC) -o $@ $(DINITOBJ) $(LDFLAGS) $(LDLIBS) Err bitreich.org 70 i Err bitreich.org 70 1diff --git a/TODO b/TODO /scm/dedup/file/TODO.gph bitreich.org 70 i@@ -1,5 +1,4 @@ Err bitreich.org 70 i Use a ring buffer in the chunker (avoid memmove() call) Err bitreich.org 70 i Create a library archive out of the blake2b files and link with it Err bitreich.org 70 i pledge/unveil support Err bitreich.org 70 i-Implement dup-check(1) Err bitreich.org 70 i Use flock() to avoid corruption Err bitreich.org 70 1diff --git a/bcompress.c b/bcompress.c /scm/dedup/file/bcompress.c.gph bitreich.org 70 i@@ -25,6 +25,7 @@ static int bccreat(struct bctx *bctx, char *path, int mode, struct bparam *bpar) Err bitreich.org 70 i static int bcopen(struct bctx *bctx, char *path, int flags, int mode, struct bparam *bpar); Err bitreich.org 70 i static int bcput(struct bctx *bctx, void *buf, size_t n, unsigned char *md); Err bitreich.org 70 i static int bcget(struct bctx *bctx, unsigned char *md, void *buf, size_t *n); Err bitreich.org 70 i+static int bccheck(struct bctx *bctx, unsigned char *md); Err bitreich.org 70 i static int bcsync(struct bctx *bctx); Err bitreich.org 70 i static int bcclose(struct bctx *bctx); Err bitreich.org 70 i Err bitreich.org 70 i@@ -33,6 +34,7 @@ static struct bops bops = { Err bitreich.org 70 i .open = bcopen, Err bitreich.org 70 i .put = bcput, Err bitreich.org 70 i .get = bcget, Err bitreich.org 70 i+ .check = bccheck, Err bitreich.org 70 i .sync = bcsync, Err bitreich.org 70 i .close = bcclose, Err bitreich.org 70 i }; Err bitreich.org 70 i@@ -236,6 +238,15 @@ bcget(struct bctx *bctx, unsigned char *md, void *buf, size_t *n) Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i static int Err bitreich.org 70 i+bccheck(struct bctx *bctx, unsigned char *md) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct bops *bops = bstorageops(); Err bitreich.org 70 i+ Err bitreich.org 70 i+ return bops->check(bctx, md); Err bitreich.org 70 i+ Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+static int Err bitreich.org 70 i bcsync(struct bctx *bctx) Err bitreich.org 70 i { Err bitreich.org 70 i struct bops *bops = bstorageops(); Err bitreich.org 70 1diff --git a/block.c b/block.c /scm/dedup/file/block.c.gph bitreich.org 70 i@@ -78,6 +78,18 @@ bget(struct bctx *bctx, unsigned char *md, void *buf, size_t *n) Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i int Err bitreich.org 70 i+bcheck(struct bctx *bctx, unsigned char *md) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct bops *bops; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (bctx == NULL || md == NULL) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ Err bitreich.org 70 i+ bops = bcompressops(); Err bitreich.org 70 i+ return bops->check(bctx, md); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i bsync(struct bctx *bctx) Err bitreich.org 70 i { Err bitreich.org 70 i struct bops *bops; Err bitreich.org 70 1diff --git a/block.h b/block.h /scm/dedup/file/block.h.gph bitreich.org 70 i@@ -17,6 +17,7 @@ struct bops { Err bitreich.org 70 i int (*open)(struct bctx *bctx, char *path, int flags, int mode, struct bparam *bpar); Err bitreich.org 70 i int (*put)(struct bctx *bctx, void *buf, size_t n, unsigned char *md); Err bitreich.org 70 i int (*get)(struct bctx *bctx, unsigned char *md, void *buf, size_t *n); Err bitreich.org 70 i+ int (*check)(struct bctx *bctx, unsigned char *md); Err bitreich.org 70 i int (*sync)(struct bctx *bctx); Err bitreich.org 70 i int (*close)(struct bctx *bctx); Err bitreich.org 70 i }; Err bitreich.org 70 i@@ -26,6 +27,7 @@ extern int bcreat(char *path, int mode, struct bparam *bpar, struct bctx **bctx) Err bitreich.org 70 i extern int bopen(char *path, int flags, int mode, struct bparam *bpar, struct bctx **bctx); Err bitreich.org 70 i extern int bput(struct bctx *bctx, void *buf, size_t n, unsigned char *md); Err bitreich.org 70 i extern int bget(struct bctx *bctx, unsigned char *md, void *buf, size_t *n); Err bitreich.org 70 i+extern int bcheck(struct bctx *bctx, unsigned char *md); Err bitreich.org 70 i extern int bsync(struct bctx *bctx); Err bitreich.org 70 i extern int bclose(struct bctx *bctx); Err bitreich.org 70 i struct bparam *bparamdef(void); Err bitreich.org 70 1diff --git a/bstorage.c b/bstorage.c /scm/dedup/file/bstorage.c.gph bitreich.org 70 i@@ -51,6 +51,7 @@ static int bscreat(struct bctx *bctx, char *path, int mode, struct bparam *bpar) Err bitreich.org 70 i static int bsopen(struct bctx *bctx, char *path, int flags, int mode, struct bparam *bpar); Err bitreich.org 70 i static int bsput(struct bctx *bctx, void *buf, size_t n, unsigned char *md); Err bitreich.org 70 i static int bsget(struct bctx *bctx, unsigned char *md, void *buf, size_t *n); Err bitreich.org 70 i+static int bscheck(struct bctx *bctx, unsigned char *md); Err bitreich.org 70 i static int bssync(struct bctx *bctx); Err bitreich.org 70 i static int bsclose(struct bctx *bctx); Err bitreich.org 70 i Err bitreich.org 70 i@@ -59,6 +60,7 @@ static struct bops bops = { Err bitreich.org 70 i .open = bsopen, Err bitreich.org 70 i .put = bsput, Err bitreich.org 70 i .get = bsget, Err bitreich.org 70 i+ .check = bscheck, Err bitreich.org 70 i .sync = bssync, Err bitreich.org 70 i .close = bsclose, Err bitreich.org 70 i }; Err bitreich.org 70 i@@ -515,6 +517,53 @@ bsget(struct bctx *bctx, unsigned char *md, void *buf, size_t *n) Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i+/* Err bitreich.org 70 i+ * Lookup the block and rehash it. Check that the Err bitreich.org 70 i+ * resulting hash matches the given hash. Err bitreich.org 70 i+ */ Err bitreich.org 70 i+static int Err bitreich.org 70 i+bscheck(struct bctx *bctx, unsigned char *md) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ struct sctx *sctx; Err bitreich.org 70 i+ struct bd key, *bd; Err bitreich.org 70 i+ void *buf; Err bitreich.org 70 i+ Err bitreich.org 70 i+ sctx = bctx->sctx; Err bitreich.org 70 i+ Err bitreich.org 70 i+ /* Lookup block in the cache */ Err bitreich.org 70 i+ memcpy(key.md, md, MDSIZE); Err bitreich.org 70 i+ bd = RB_FIND(bdcache, &sctx->bdcache, &key); Err bitreich.org 70 i+ if (bd == NULL) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ Err bitreich.org 70 i+ buf = malloc(bd->size); Err bitreich.org 70 i+ if (buf == NULL) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (lseek(sctx->fd, bd->offset, SEEK_SET) < 0) { Err bitreich.org 70 i+ free(buf); Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (xread(sctx->fd, buf, bd->size) != bd->size) { Err bitreich.org 70 i+ free(buf); Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (bhash(buf, bd->size, key.md) < 0) { Err bitreich.org 70 i+ free(buf); Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (memcmp(key.md, md, MDSIZE) != 0) { Err bitreich.org 70 i+ free(buf); Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ free(buf); Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i /* Sync block header to storage */ Err bitreich.org 70 i static int Err bitreich.org 70 i bssync(struct bctx *bctx) Err bitreich.org 70 1diff --git a/dotest b/dotest /scm/dedup/file/dotest.gph bitreich.org 70 i@@ -9,6 +9,8 @@ test0() Err bitreich.org 70 i ./dup-init -Z none "$repo" Err bitreich.org 70 i ./dup-pack -r "$repo" snap0 < "$data" Err bitreich.org 70 i ./dup-pack -r "$repo" snap1 < "$data" Err bitreich.org 70 i+ ./dup-check -r "$repo" snap0 Err bitreich.org 70 i+ ./dup-check -r "$repo" snap1 Err bitreich.org 70 i du -sh "$repo" Err bitreich.org 70 i sum0=`sha1sum "$data" | awk '{print $1}'` Err bitreich.org 70 i sum1=`./dup-unpack -r "$repo" snap0 | sha1sum | awk '{print $1}'` Err bitreich.org 70 i@@ -26,6 +28,8 @@ test1() Err bitreich.org 70 i ./dup-init -Z snappy "$repo" Err bitreich.org 70 i ./dup-pack -r "$repo" snap0 < "$data" Err bitreich.org 70 i ./dup-pack -r "$repo" snap1 < "$data" Err bitreich.org 70 i+ ./dup-check -r "$repo" snap0 Err bitreich.org 70 i+ ./dup-check -r "$repo" snap1 Err bitreich.org 70 i du -sh "$repo" Err bitreich.org 70 i sum0=`sha1sum "$data" | awk '{print $1}'` Err bitreich.org 70 i sum1=`./dup-unpack -r "$repo" snap0 | sha1sum | awk '{print $1}'` Err bitreich.org 70 1diff --git a/dup-check.1 b/dup-check.1 /scm/dedup/file/dup-check.1.gph bitreich.org 70 i@@ -0,0 +1,25 @@ Err bitreich.org 70 i+.Dd April 25, 2019 Err bitreich.org 70 i+.Dt DUP-CHECK 1 Err bitreich.org 70 i+.Os Err bitreich.org 70 i+.Sh NAME Err bitreich.org 70 i+.Nm dup-check Err bitreich.org 70 i+.Nd Check snapshot consistency Err bitreich.org 70 i+.Sh SYNOPSIS Err bitreich.org 70 i+.Nm dup-check Err bitreich.org 70 i+.Op Fl v Err bitreich.org 70 i+.Op Fl r Ar repo Err bitreich.org 70 i+.Ar name Err bitreich.org 70 i+.Sh DESCRIPTION Err bitreich.org 70 i+.Nm Err bitreich.org 70 i+checks that a snapshot is internally consistent. Err bitreich.org 70 i+.Sh OPTIONS Err bitreich.org 70 i+.Bl -tag -width "-r repo" Err bitreich.org 70 i+.It Fl r Ar repo Err bitreich.org 70 i+Repository directory. Err bitreich.org 70 i+By default the current working directory is used. 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/dup-check.c b/dup-check.c /scm/dedup/file/dup-check.c.gph bitreich.org 70 i@@ -0,0 +1,81 @@ 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+ Err bitreich.org 70 i+#include "arg.h" Err bitreich.org 70 i+#include "block.h" Err bitreich.org 70 i+#include "config.h" Err bitreich.org 70 i+#include "snap.h" 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 int Err bitreich.org 70 i+check(struct sctx *sctx, struct bctx *bctx) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ unsigned char md[MDSIZE]; Err bitreich.org 70 i+ int sn; Err bitreich.org 70 i+ Err bitreich.org 70 i+ while ((sn = sget(sctx, md)) == MDSIZE) { Err bitreich.org 70 i+ if (bcheck(bctx, md) < 0) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ if (sn < 0) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ return 0; 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] [-r repo] name\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 path[PATH_MAX]; Err bitreich.org 70 i+ struct sctx *sctx; Err bitreich.org 70 i+ struct bctx *bctx; Err bitreich.org 70 i+ struct bparam bparam; Err bitreich.org 70 i+ char *repo = "."; Err bitreich.org 70 i+ Err bitreich.org 70 i+ ARGBEGIN { Err bitreich.org 70 i+ case 'r': Err bitreich.org 70 i+ repo = 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+ Err bitreich.org 70 i+ snprintf(path, sizeof(path), "%s/archive/%s", repo, argv[0]); Err bitreich.org 70 i+ if (sopen(path, O_RDONLY, 0600, &sctx) < 0) Err bitreich.org 70 i+ errx(1, "sopen: %s: failed", path); Err bitreich.org 70 i+ Err bitreich.org 70 i+ snprintf(path, sizeof(path), "%s/storage", repo); Err bitreich.org 70 i+ if (bopen(path, O_RDONLY, 0600, &bparam, &bctx) <0) Err bitreich.org 70 i+ errx(1, "bopen: %s: failed", path); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (check(sctx, bctx) < 0) Err bitreich.org 70 i+ errx(1, "dedup: failed"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (bclose(bctx) < 0) Err bitreich.org 70 i+ errx(1, "bclose: failed"); Err bitreich.org 70 i+ if (sclose(sctx) < 0) Err bitreich.org 70 i+ errx(1, "sclose: failed"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 .