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 }