From 4921ff6f80a3e82e80197c5ea2379ef42ea2cc57 Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Wed, 21 Aug 2013 22:03:09 +0200 Subject: [PATCH] Saves in the content files info only for positions with at least one hash. Also checks that when loading. --- state.c | 50 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/state.c b/state.c index c95b18b7..653c01a1 100644 --- a/state.c +++ b/state.c @@ -822,19 +822,34 @@ static void state_content_check(struct snapraid_state* state, const char* path) } /** - * Checks if a block position is used by at least one disk. + * Checks if a block position is used by at least one disk + * and has a hash value. + * Note that we include DELETED blocks, but only if they have a not NULL hash. */ -static int is_block_used(struct snapraid_state* state, block_off_t pos) +static int position_has_hash(struct snapraid_state* state, block_off_t pos) { tommy_node* i; + unsigned j; /* check for each disk if block is really used */ for(i=state->disklist;i!=0;i=i->next) { struct snapraid_disk* disk = i->data; struct snapraid_block* block = disk_block_get(disk, pos); - if (block != BLOCK_EMPTY) + unsigned block_state = block_state_get(block); + + switch (block_state) { + case BLOCK_STATE_BLK : + case BLOCK_STATE_CHG : return 1; + case BLOCK_STATE_DELETED : + for(j=0;jhash[j] != 0) + break; + if (j != HASH_SIZE) + return 1; + break; + } } return 0; @@ -1066,6 +1081,7 @@ static void state_read_text(struct snapraid_state* state, const char* path, STRE /* "off" command */ block_off_t v_pos; struct snapraid_deleted* deleted; + snapraid_info info; if (!disk) { fprintf(stderr, "Unexpected 'off' specification in '%s' at line %u\n", path, line); @@ -1109,6 +1125,13 @@ static void state_read_text(struct snapraid_state* state, const char* path, STRE /* insert the block in the block array */ tommy_array_grow(&disk->blockarr, v_pos + 1); tommy_array_set(&disk->blockarr, v_pos, &deleted->block); + + /* set a fake info block, in case of upgrading from an old version */ + /* the real info, if present, will overwrite this */ + info = info_make(save_time, 0, 0); + + /* insert the info in the array */ + info_set(&state->infoarr, v_pos, info); } else if (strcmp(tag, "file") == 0) { /* file */ char sub[PATH_MAX]; @@ -1637,7 +1660,7 @@ static void state_write_text(struct snapraid_state* state, STREAM* f) info_has_rehash = 0; /* if there is a rehash info */ for(b=0;binfoarr, b); /* only if there is some info to store */ @@ -1875,7 +1898,7 @@ static void state_write_text(struct snapraid_state* state, STREAM* f) /* write the info for each block */ for(b=0;binfoarr, b); /* save only stuffs different than 0 */ @@ -2256,6 +2279,21 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST /* insert the info in the array */ info_set(&state->infoarr, v_pos, info); + /* ensure that an info is present only for used positions */ + if (position_has_hash(state, v_pos)) { + if (!info) { + decoding_error(path, f); + fprintf(stderr, "Internal incosistency for missing info!\n"); + exit(EXIT_FAILURE); + } + } else { + if (info) { + decoding_error(path, f); + fprintf(stderr, "Internal incosistency for unexpected info!\n"); + exit(EXIT_FAILURE); + } + } + /* go to next block */ ++v_pos; --v_count; @@ -2663,7 +2701,7 @@ static void state_write_binary(struct snapraid_state* state, STREAM* f) info_has_rehash = 0; /* if there is a rehash info */ for(b=0;binfoarr, b); /* only if there is some info to store */