diff --git a/elem.h b/elem.h index 50d5bf3a..a9adf1e0 100644 --- a/elem.h +++ b/elem.h @@ -481,7 +481,7 @@ static inline int block_has_any_hash(const struct snapraid_block* block) /** * Checks if the specified block is part of a file. * - * Note that EMPTY return 0. + * Note that EMPTY / DELETED return 0. */ static inline int block_has_file(const struct snapraid_block* block) { @@ -493,7 +493,7 @@ static inline int block_has_file(const struct snapraid_block* block) /** * Checks if the block has an invalid parity than needs to be updated. * - * Note that EMPTY return 0. + * Note that EMPTY / BLK return 0. */ static inline int block_has_invalid_parity(const struct snapraid_block* block) { diff --git a/state.c b/state.c index 3c6c34a8..dfead809 100644 --- a/state.c +++ b/state.c @@ -992,7 +992,7 @@ static void state_read_text(struct snapraid_state* state, const char* path, STRE } /* if the block has a hash */ - if (tag[0] != 'n') { + if (block_has_any_hash(block)) { snapraid_info info; /* set a fake info block, in case of upgrading from an old version */ @@ -1019,6 +1019,11 @@ static void state_read_text(struct snapraid_state* state, const char* path, STRE exit(EXIT_FAILURE); } + if (v_pos >= blockmax) { + fprintf(stderr, "Internal position inconsistency in 'inf' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + } + c = sgetc(f); if (c != ' ') { fprintf(stderr, "Invalid 'inf' specification in '%s' at line %u\n", path, line); @@ -1068,7 +1073,6 @@ 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); @@ -1087,6 +1091,10 @@ static void state_read_text(struct snapraid_state* state, const char* path, STRE exit(EXIT_FAILURE); } + /* note that here we don't have a valid blockmax because we have not */ + /* yet processed all the disks with all the files */ + /* and then we cannot ensure that v_pos < blockmax */ + deleted->block.parity_pos = v_pos; /* read the hash */ @@ -1113,12 +1121,17 @@ static void state_read_text(struct snapraid_state* state, const char* path, STRE 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); + /* if the block has an hash */ + if (block_has_any_hash(&deleted->block)) { + snapraid_info info; - /* insert the info in the array */ - info_set(&state->infoarr, v_pos, info); + /* 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]; @@ -1884,28 +1897,25 @@ static void state_write_text(struct snapraid_state* state, STREAM* f) /* write the info for each block */ for(b=0;binfoarr, b); + snapraid_info info = info_get(&state->infoarr, b); - /* save only stuffs different than 0 */ - if (info != 0) { - sputsl("inf ", f); + /* save only stuffs different than 0 */ + if (info != 0) { + sputsl("inf ", f); - sputu32(b, f); - sputc(' ', f); - sputu32(info, f); - if (info_get_bad(info)) { - sputsl(" bad", f); - } - if (info_get_rehash(info)) { - sputsl(" rehash", f); - } - sputeol(f); - if (serror(f)) { - fprintf(stderr, "Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - exit(EXIT_FAILURE); - } + sputu32(b, f); + sputc(' ', f); + sputu32(info, f); + if (info_get_bad(info)) { + sputsl(" bad", f); + } + if (info_get_rehash(info)) { + sputsl(" rehash", f); + } + sputeol(f); + if (serror(f)) { + fprintf(stderr, "Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + exit(EXIT_FAILURE); } } }