dedup

data deduplication program
git clone git://git.2f30.org/dedup.git
Log | Files | Refs | README | LICENSE

dcheck.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 }