tdcheck.c - dedup - data deduplication program
HTML git clone git://bitreich.org/dedup/ git://hg6vgqziawt5s4dj.onion/dedup/
DIR Log
DIR Files
DIR Refs
DIR Tags
DIR README
DIR LICENSE
---
tdcheck.c (2945B)
---
1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <sys/file.h>
4
5 #include <err.h>
6 #include <fcntl.h>
7 #include <stdio.h>
8 #include <stdint.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12
13 #include "arg.h"
14 #include "blake2.h"
15 #include "dedup.h"
16
17 static struct snap_hdr snap_hdr;
18 static struct blk_hdr blk_hdr;
19 static int ifd;
20 static int sfd;
21 static int hash_algo = HASH_BLAKE2B;
22 static int compr_algo = COMPR_LZ4;
23
24 int verbose;
25 char *argv0;
26
27 static void
28 print_md(FILE *fp, uint8_t *md, size_t size)
29 {
30 size_t i;
31
32 for (i = 0; i < size; i++)
33 fprintf(fp, "%02x", md[i]);
34 }
35
36 /*
37 * Hash every block referenced by the given snapshot
38 * and compare its hash with the one stored in the corresponding
39 * block descriptor.
40 */
41 static int
42 check_snap(struct snap *snap, void *arg)
43 {
44 struct compr_ctx ctx;
45 uint8_t *buf;
46 int *ret = arg;
47 uint64_t i;
48
49 if (verbose > 0) {
50 fprintf(stderr, "Checking snapshot: ");
51 print_md(stderr, snap->md, sizeof(snap->md));
52 fputc('\n', stderr);
53 }
54
55 if (compr_init(&ctx, compr_algo) < 0)
56 errx(1, "compr_init failed");
57 buf = alloc_buf(compr_size(&ctx, BLKSIZE_MAX));
58 for (i = 0; i < snap->nr_blk_descs; i++) {
59 uint8_t md[MD_SIZE];
60 struct blk_desc *blk_desc;
61
62 blk_desc = &snap->blk_desc[i];
63 read_blk(sfd, buf, blk_desc);
64 hash_blk(buf, blk_desc->size, md, hash_algo);
65
66 if (memcmp(blk_desc->md, md, sizeof(blk_desc->md)) == 0)
67 continue;
68
69 fprintf(stderr, "Block hash mismatch\n");
70 fprintf(stderr, " Expected hash: ");
71 print_md(stderr, blk_desc->md, sizeof(blk_desc->md));
72 fputc('\n', stderr);
73 fprintf(stderr, " Actual hash: ");
74 print_md(stderr, md, sizeof(md));
75 fputc('\n', stderr);
76 fprintf(stderr, " Offset: %llu\n",
77 (unsigned long long)blk_desc->offset);
78 fprintf(stderr, " Size: %llu\n",
79 (unsigned long long)blk_desc->size);
80 *ret = -1;
81 }
82 free_buf(buf);
83 compr_final(&ctx);
84 return WALK_CONTINUE;
85 }
86
87 static void
88 init(void)
89 {
90 ifd = open(SNAPSF, O_RDONLY, 0600);
91 if (ifd < 0)
92 err(1, "open %s", SNAPSF);
93
94 sfd = open(STOREF, O_RDONLY, 0600);
95 if (sfd < 0)
96 err(1, "open %s", STOREF);
97
98 if (flock(ifd, LOCK_NB | LOCK_EX) < 0 ||
99 flock(sfd, LOCK_NB | LOCK_EX) < 0)
100 err(1, "flock");
101
102 xlseek(ifd, 0, SEEK_SET);
103 load_snap_hdr(ifd, &snap_hdr);
104 xlseek(sfd, 0, SEEK_SET);
105 load_blk_hdr(sfd, &blk_hdr, &compr_algo, &hash_algo);
106 }
107
108 static void
109 term(void)
110 {
111 close(ifd);
112 close(sfd);
113 }
114
115 static void
116 usage(void)
117 {
118 fprintf(stderr, "usage: %s [-v] [repo]\n", argv0);
119 exit(1);
120 }
121
122 int
123 main(int argc, char *argv[])
124 {
125 char *repo = NULL;
126 int ret;
127
128 ARGBEGIN {
129 case 'v':
130 verbose++;
131 break;
132 default:
133 usage();
134 } ARGEND
135
136 switch (argc) {
137 case 0:
138 repo = ".";
139 break;
140 case 1:
141 repo = argv[0];
142 break;
143 default:
144 usage();
145 };
146
147 if (chdir(repo) < 0)
148 err(1, "chdir: %s", repo);
149
150 init();
151 ret = 0;
152 walk_snap(ifd, &snap_hdr, check_snap, &ret);
153 if (ret != 0)
154 errx(1, "%s or %s is corrupted", SNAPSF, STOREF);
155 term();
156 return 0;
157 }