diff --git a/Makefile.am b/Makefile.am index 50880983..61f94523 100644 --- a/Makefile.am +++ b/Makefile.am @@ -532,23 +532,17 @@ endif $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR6) fix -l test.log $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync - echo --- Delete some files and create some new, sync and check in multiple steps using text content + echo --- Delete some files and create some new, sync and check in multiple steps rm bench/disk1/a/4* rm bench/disk2/a/5* rm bench/disk3/a/6* rm bench/disk4/a/6* - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -B 10 sync --test-force-content-text - cp bench/content bench/content.txt + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -B 10 sync $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) test-rewrite - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) --test-force-content-text test-rewrite - cmp bench/content bench/content.txt $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check -l test.log $(TESTENV) ./mktest$(EXEEXT) generate 4 6 $(CHECKCOUNT) $(CHECKSIZE) - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -B 100 sync --test-force-content-text - cp bench/content bench/content.txt + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -B 100 sync $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) test-rewrite - $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-content-text test-rewrite - cmp bench/content bench/content.txt $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -B 1000 sync $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check -l test.log $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync diff --git a/cmdline/snapraid.c b/cmdline/snapraid.c index a20f7cb1..a80e659f 100644 --- a/cmdline/snapraid.c +++ b/cmdline/snapraid.c @@ -234,7 +234,6 @@ void config(char* conf, size_t conf_size, const char* argv0) #define OPT_TEST_FORCE_SCRUB_AT 271 #define OPT_TEST_FORCE_SCRUB_EVEN 272 #define OPT_TEST_FORCE_CONTENT_WRITE 273 -#define OPT_TEST_FORCE_CONTENT_TEXT 274 #define OPT_TEST_SKIP_CONTENT_CHECK 275 #define OPT_TEST_SKIP_PARITY_ACCESS 276 #define OPT_TEST_EXPECT_FAILURE 277 @@ -327,9 +326,6 @@ struct option long_options[] = { /* Force write of the content file even if no modification is done */ { "test-force-content-write", 0, 0, OPT_TEST_FORCE_CONTENT_WRITE }, - /* Force the use of text content file */ - { "test-force-content-text", 0, 0, OPT_TEST_FORCE_CONTENT_TEXT }, - /* Relax the checks done at the content file */ { "test-skip-content-check", 0, 0, OPT_TEST_SKIP_CONTENT_CHECK }, @@ -684,9 +680,6 @@ int main(int argc, char* argv[]) case OPT_TEST_FORCE_CONTENT_WRITE : opt.force_content_write = 1; break; - case OPT_TEST_FORCE_CONTENT_TEXT : - opt.force_content_text = 1; - break; case OPT_TEST_EXPECT_FAILURE : /* invert the exit codes */ exit_success = 1; diff --git a/cmdline/state.c b/cmdline/state.c index 9c04198c..10db227d 100644 --- a/cmdline/state.c +++ b/cmdline/state.c @@ -1455,1475 +1455,6 @@ static int is_block_deleted(struct snapraid_disk* disk, block_off_t pos) return block_state_get(block) == BLOCK_STATE_DELETED; } -static void state_read_text(struct snapraid_state* state, const char* path, STREAM* f, time_t save_time) -{ - struct snapraid_disk* disk; - struct snapraid_file* file; - block_off_t blockidx; - block_off_t blockmax; - unsigned line; - unsigned count_file; - unsigned count_hardlink; - unsigned count_symlink; - unsigned count_dir; - block_off_t b; - - disk = 0; - file = 0; - line = 1; - blockidx = 0; - blockmax = 0; - count_file = 0; - count_hardlink = 0; - count_symlink = 0; - count_dir = 0; - - while (1) { - char buffer[PATH_MAX]; - char tag[PATH_MAX]; - int ret; - int c; - - /* read the command */ - ret = sgettok(f, tag, sizeof(tag)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Error reading the configuration file '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* skip only one space if present */ - c = sgetc(f); - if (c != ' ') { - sungetc(c, f); - } - - if (strcmp(tag, "blk") == 0 || strcmp(tag, "new") == 0 - || strcmp(tag, "chg") == 0 || strcmp(tag, "rep") == 0 - ) { - /* "blk"/""new"/"chg"/"rep" command */ - block_off_t v_pos; - struct snapraid_block* block; - - if (!file) { - /* LCOV_EXCL_START */ - log_fatal("Unexpected '%s' specification in '%s' at line %u\n", tag, path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - ret = sgetu32(f, &v_pos); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid '%s' specification in '%s' at line %u\n", tag, path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - if (blockidx >= file->blockmax) { - /* LCOV_EXCL_START */ - log_fatal("Internal inconsistency in '%s' specification in '%s' at line %u\n", tag, path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - block = &file->blockvec[blockidx]; - - if (block->parity_pos != POS_INVALID) { - /* LCOV_EXCL_START */ - log_fatal("Internal inconsistency in '%s' specification in '%s' at line %u\n", tag, path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* set the parity only if present */ - switch (tag[0]) { - case 'b' : - block_state_set(block, BLOCK_STATE_BLK); - break; - case 'n' : - /* deprecated NEW blocks are converted to CHG ones */ - block_state_set(block, BLOCK_STATE_CHG); - break; - case 'c' : - block_state_set(block, BLOCK_STATE_CHG); - break; - case 'r' : - block_state_set(block, BLOCK_STATE_REP); - break; - } - - block->parity_pos = v_pos; - - /* keep track of the max block number used in parity */ - if (v_pos + 1 > blockmax) - blockmax = v_pos + 1; - - /* read the hash only for 'blk/chg/rep', and not for 'new' */ - if (tag[0] != 'n') { - c = sgetc(f); - if (c != ' ') { - /* LCOV_EXCL_START */ - log_fatal("Invalid '%s' specification in '%s' at line %u\n", tag, path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - ret = sgethex(f, block->hash, HASH_SIZE); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid '%s' specification in '%s' at line %u\n", tag, path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - } else { - /* set the ZERO hash for deprecated NEW blocks */ - hash_zero_set(block->hash); - } - - /* if the block contains a hash of past data */ - /* and we are clearing such undeterminated hashes */ - if (state->clear_past_hash - && block_has_past_hash(block) - ) { - /* set the hash value to INVALID */ - hash_invalid_set(block->hash); - } - - /* if we are disabling the copy optimization */ - /* we want also to clear any already previously stored information */ - /* in other sync commands */ - /* note that this is required only in sync, and we detect */ - /* this using the clear_past_hash flag */ - if (state->clear_past_hash - && state->opt.force_nocopy - && block_state_get(block) == BLOCK_STATE_REP - ) { - /* set the hash value to INVALID */ - hash_invalid_set(block->hash); - /* convert from REP to CHG block */ - block_state_set(block, BLOCK_STATE_CHG); - } - - /* if we want a full sync, marks block as invalid parity */ - /* note that we do this after the force_nocopy option */ - /* to avoid to mixup the two things */ - if (state->opt.force_full - && block_state_get(block) == BLOCK_STATE_BLK) { - /* convert from BLK to REP */ - block_state_set(block, BLOCK_STATE_REP); - } - - /* we must not overwrite existing blocks */ - if (fs_par2block_get(disk, v_pos) != BLOCK_EMPTY) { - /* LCOV_EXCL_START */ - log_fatal("Internal inconsistency for '%s' specification in '%s' at line %u\n", tag, path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* insert the block in the block array */ - fs_par2block_set(disk, v_pos, block); - - /* check for termination of the block list */ - ++blockidx; - if (blockidx == file->blockmax) { - file = 0; - disk = 0; - } - } else if (strcmp(tag, "inf") == 0) { - /* "inf" command */ - block_off_t v_pos; - snapraid_info info; - int rehash; - int bad; - int justsynced; - uint32_t t; - - ret = sgetu32(f, &v_pos); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'inf' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - if (v_pos >= blockmax) { - /* LCOV_EXCL_START */ - log_fatal("Internal inconsistency in position for 'inf' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - c = sgetc(f); - if (c != ' ') { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'inf' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - ret = sgetu32(f, &t); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'inf' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* read extra tags if present */ - rehash = 0; - bad = 0; - justsynced = 0; - c = sgetc(f); - while (c == ' ') { - ret = sgettok(f, buffer, sizeof(buffer)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'inf' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - if (strcmp(buffer, "bad") == 0) { - bad = 1; - } else if (strcmp(buffer, "rehash") == 0) { - rehash = 1; - - if (state->prevhash == HASH_UNDEFINED) { - /* LCOV_EXCL_START */ - log_fatal("Internal inconsistency for missing previous checksum in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - } else if (strcmp(buffer, "justsynced") == 0) { - justsynced = 1; - } else { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'inf' specification '%s' in '%s' at line %u\n", buffer, path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - c = sgetc(f); - } - sungetc(c, f); - - info = info_make(t, bad, rehash, justsynced); - - /* insert the info in the array */ - info_set(&state->infoarr, v_pos, info); - } else if (strcmp(tag, "off") == 0) { - /* "off" command */ - block_off_t v_pos; - struct snapraid_deleted* deleted; - - if (!disk) { - /* LCOV_EXCL_START */ - log_fatal("Unexpected 'off' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* allocate a new deleted block */ - deleted = deleted_alloc(); - - ret = sgetu32(f, &v_pos); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'off' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - deleted->block.parity_pos = v_pos; - - /* read the hash */ - c = sgetc(f); - if (c != ' ') { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'off' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* set the hash only if present */ - ret = sgethex(f, deleted->block.hash, HASH_SIZE); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'off' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* if we are clearing undeterminated hashes */ - if (state->clear_past_hash) { - /* set the hash value to INVALID */ - hash_invalid_set(deleted->block.hash); - } - - /* we must not overwrite existing blocks */ - if (fs_par2block_get(disk, v_pos) != BLOCK_EMPTY) { - /* LCOV_EXCL_START */ - log_fatal("Internal inconsistency for 'off' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* insert it in the list of deleted blocks */ - tommy_list_insert_tail(&disk->deletedlist, &deleted->node, deleted); - - /* insert the block in the block array */ - fs_par2block_set(disk, v_pos, &deleted->block); - } else if (strcmp(tag, "file") == 0) { - /* file */ - char sub[PATH_MAX]; - uint64_t v_size; - uint64_t v_mtime_sec; - uint32_t v_mtime_nsec; - uint64_t v_inode; - - if (file) { - /* LCOV_EXCL_START */ - log_fatal("Missing 'blk' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - ret = sgettok(f, buffer, sizeof(buffer)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'file' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - c = sgetc(f); - if (c != ' ') { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'file' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - ret = sgetu64(f, &v_size); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'file' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - c = sgetc(f); - if (c != ' ') { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'file' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - ret = sgetu64(f, &v_mtime_sec); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'file' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - c = sgetc(f); - if (c == '.') { /* the nanosecond field is present only from version 1.14 */ - ret = sgetu32(f, &v_mtime_nsec); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'file' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - c = sgetc(f); - } else { - /* use a special value, meaning that we don't have this information */ - v_mtime_nsec = STAT_NSEC_INVALID; - } - - if (c != ' ') { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'file' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - ret = sgetu64(f, &v_inode); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'file' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - c = sgetc(f); - if (c != ' ') { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'file' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - ret = sgetline(f, sub, sizeof(sub)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'file' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - if (!*sub) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'file' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* find the disk */ - disk = find_disk(state, buffer); - if (!disk) { - /* LCOV_EXCL_START */ - log_fatal("Disk named '%s' not found in '%s' at line %u\n", buffer, path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* allocate the file */ - file = file_alloc(state->block_size, sub, v_size, v_mtime_sec, v_mtime_nsec, v_inode, 0); - - /* insert the file in the file containers */ - tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); - tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub)); - tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec)); - tommy_list_insert_tail(&disk->filelist, &file->nodelist, file); - - /* start the block allocation of the file */ - blockidx = 0; - - /* check for empty file */ - if (blockidx == file->blockmax) { - file = 0; - disk = 0; - } - - /* stat */ - ++count_file; - } else if (strcmp(tag, "hole") == 0) { - /* hole */ - - if (file) { - /* LCOV_EXCL_START */ - log_fatal("Missing 'blk' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - ret = sgettok(f, buffer, sizeof(buffer)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'hole' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* find the disk */ - disk = find_disk(state, buffer); - if (!disk) { - /* LCOV_EXCL_START */ - log_fatal("Disk named '%s' not found in '%s' at line %u\n", buffer, path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - } else if (strcmp(tag, "symlink") == 0) { - /* symlink */ - char sub[PATH_MAX]; - char linkto[PATH_MAX]; - char tokento[32]; - struct snapraid_link* link; - - ret = sgettok(f, buffer, sizeof(buffer)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'symlink' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - c = sgetc(f); - if (c != ' ') { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'symlink' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - ret = sgetline(f, sub, sizeof(sub)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'symlink' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - c = sgeteol(f); - if (c != '\n') { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'symlink' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - ++line; - - ret = sgettok(f, tokento, sizeof(tokento)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'symlink' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - if (strcmp(tokento, "to") != 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'symlink' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - c = sgetc(f); - if (c != ' ') { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'symlink' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - ret = sgetline(f, linkto, sizeof(linkto)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'symlink' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - if (!*sub || !*linkto) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'symlink' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* find the disk */ - disk = find_disk(state, buffer); - if (!disk) { - /* LCOV_EXCL_START */ - log_fatal("Disk named '%s' not found in '%s' at line %u\n", buffer, path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* allocate the link as symbolic link */ - link = link_alloc(sub, linkto, FILE_IS_SYMLINK); - - /* insert the link in the link containers */ - tommy_hashdyn_insert(&disk->linkset, &link->nodeset, link, link_name_hash(link->sub)); - tommy_list_insert_tail(&disk->linklist, &link->nodelist, link); - - /* stat */ - ++count_symlink; - } else if (strcmp(tag, "hardlink") == 0) { - /* hardlink */ - char sub[PATH_MAX]; - char linkto[PATH_MAX]; - char tokento[32]; - struct snapraid_link* link; - - ret = sgettok(f, buffer, sizeof(buffer)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'hardlink' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - c = sgetc(f); - if (c != ' ') { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'hardlink' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - ret = sgetline(f, sub, sizeof(sub)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'hardlink' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - c = sgeteol(f); - if (c != '\n') { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'hardlink' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - ++line; - - ret = sgettok(f, tokento, sizeof(tokento)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'hardlink' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - if (strcmp(tokento, "to") != 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'hardlink' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - c = sgetc(f); - if (c != ' ') { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'hardlink' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - ret = sgetline(f, linkto, sizeof(linkto)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'hardlink' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - if (!*sub || !*linkto) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'hardlink' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* find the disk */ - disk = find_disk(state, buffer); - if (!disk) { - /* LCOV_EXCL_START */ - log_fatal("Disk named '%s' not found in '%s' at line %u\n", buffer, path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* allocate the link as hard link */ - link = link_alloc(sub, linkto, FILE_IS_HARDLINK); - - /* insert the link in the link containers */ - tommy_hashdyn_insert(&disk->linkset, &link->nodeset, link, link_name_hash(link->sub)); - tommy_list_insert_tail(&disk->linklist, &link->nodelist, link); - - /* stat */ - ++count_hardlink; - } else if (strcmp(tag, "dir") == 0) { - /* dir */ - char sub[PATH_MAX]; - struct snapraid_dir* dir; - - ret = sgettok(f, buffer, sizeof(buffer)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'dir' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - c = sgetc(f); - if (c != ' ') { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'dir' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - ret = sgetline(f, sub, sizeof(sub)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'dir' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - if (!*sub) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'dir' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* find the disk */ - disk = find_disk(state, buffer); - if (!disk) { - /* LCOV_EXCL_START */ - log_fatal("Disk named '%s' not found in '%s' at line %u\n", buffer, path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* allocate the dir */ - dir = dir_alloc(sub); - - /* insert the dir in the dir containers */ - tommy_hashdyn_insert(&disk->dirset, &dir->nodeset, dir, dir_name_hash(dir->sub)); - tommy_list_insert_tail(&disk->dirlist, &dir->nodelist, dir); - - /* stat */ - ++count_dir; - } else if (strcmp(tag, "checksum") == 0) { - - ret = sgettok(f, buffer, sizeof(buffer)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'checksum' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - if (strcmp(buffer, "murmur3") == 0) { - state->hash = HASH_MURMUR3; - } else if (strcmp(buffer, "spooky2") == 0) { - state->hash = HASH_SPOOKY2; - } else { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'checksum' specification '%s' in '%s' at line %u\n", buffer, path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - c = sgetc(f); - if (c == ' ') { - /* read the seed if present */ - ret = sgethex(f, state->hashseed, HASH_SIZE); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'seed' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - } else { - sungetc(c, f); - memset(state->hashseed, 0, HASH_SIZE); - } - } else if (strcmp(tag, "prevchecksum") == 0) { - - ret = sgettok(f, buffer, sizeof(buffer)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'prevchecksum' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - if (strcmp(buffer, "murmur3") == 0) { - state->prevhash = HASH_MURMUR3; - } else if (strcmp(buffer, "spooky2") == 0) { - state->prevhash = HASH_SPOOKY2; - } else { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'prevchecksum' specification '%s' in '%s' at line %u\n", buffer, path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - c = sgetc(f); - if (c != ' ') { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'prevchecksum' specification '%s' in '%s' at line %u\n", buffer, path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* read the seed */ - ret = sgethex(f, state->prevhashseed, HASH_SIZE); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'seed' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - } else if (strcmp(tag, "blksize") == 0) { - block_off_t blksize; - - ret = sgetu32(f, &blksize); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'blksize' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* without configuration, auto assign the block size */ - if (state->no_conf) { - state->block_size = blksize; - } - - if (blksize != state->block_size) { - /* LCOV_EXCL_START */ - log_fatal("Mismatching 'blksize' and 'blocksize' specification in '%s' at line %u\n", path, line); - log_fatal("Please restore the 'blocksize' value in the configuration file to '%u'\n", blksize / 1024); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - } else if (strcmp(tag, "map") == 0 || strcmp(tag, "mapping") == 0) { - struct snapraid_map* map; - char uuid[UUID_MAX]; - uint32_t v_pos; - uint32_t v_total_blocks; - uint32_t v_free_blocks; - - ret = sgettok(f, buffer, sizeof(buffer)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'map' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - c = sgetc(f); - if (c != ' ') { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'map' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - ret = sgetu32(f, &v_pos); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'map' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* from SnapRAID 7.0 the 'mapping' command includes the free space */ - if (strcmp(tag, "mapping") == 0) { - c = sgetc(f); - if (c != ' ') { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'map' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - ret = sgetu32(f, &v_total_blocks); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'map' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - c = sgetc(f); - if (c != ' ') { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'map' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - ret = sgetu32(f, &v_free_blocks); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'map' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - } else { - v_total_blocks = 0; - v_free_blocks = 0; - } - - /* check if the uuid is present */ - /* uuid must be the latest one as it could be also empty */ - c = sgetc(f); - if (c != ' ') { - sungetc(c, f); - uuid[0] = 0; - } else { - /* read the uuid */ - ret = sgettok(f, uuid, sizeof(uuid)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'map' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - } - - map = map_alloc(buffer, v_pos, v_total_blocks, v_free_blocks, uuid); - - tommy_list_insert_tail(&state->maplist, &map->node, map); - } else if (strcmp(tag, "parity") == 0) { - /* from SnapRAID 7.0 the 'parity' command includes the free space */ - char uuid[UUID_MAX]; - uint32_t v_level; - uint32_t v_total_blocks; - uint32_t v_free_blocks; - - ret = sgetu32(f, &v_level); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'parity' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - c = sgetc(f); - if (c != ' ') { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'parity' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - ret = sgetu32(f, &v_total_blocks); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'parity' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - c = sgetc(f); - if (c != ' ') { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'parity' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - ret = sgetu32(f, &v_free_blocks); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'parity' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* check if the uuid is present */ - /* uuid must be the latest one as it could be also empty */ - c = sgetc(f); - if (c != ' ') { - sungetc(c, f); - uuid[0] = 0; - } else { - /* read the uuid */ - ret = sgettok(f, uuid, sizeof(uuid)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'map' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - } - - /* auto configure if configuration is missing */ - if (state->no_conf && v_level < LEV_MAX && v_level >= state->level) - state->level = v_level + 1; - - /* if we use this parity entry */ - if (v_level < state->level) { - /* set the parity info */ - pathcpy(state->parity[v_level].uuid, sizeof(state->parity[v_level].uuid), uuid); - state->parity[v_level].total_blocks = v_total_blocks; - state->parity[v_level].free_blocks = v_free_blocks; - } - } else if (strcmp(tag, "sign") == 0) { - uint32_t sign; - - ret = sgetu32(f, &sign); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid 'sign' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* sign check not supported anymore for the text content file */ - } else if (tag[0] == 0) { - /* allow empty lines */ - sgetspace(f); - } else if (tag[0] == '#') { - ret = sgetline(f, buffer, sizeof(buffer)); - if (ret < 0) { - /* LCOV_EXCL_START */ - log_fatal("Invalid comment in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - } else { - /* LCOV_EXCL_START */ - log_fatal("Invalid command '%s' in '%s' at line %u\n", tag, path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* next line */ - c = sgeteol(f); - if (c == EOF) { - break; - } - if (c != '\n') { - /* LCOV_EXCL_START */ - log_fatal("Extra data in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - ++line; - } - - if (serror(f)) { - /* LCOV_EXCL_START */ - log_fatal("Error reading the content file '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - if (file) { - /* LCOV_EXCL_START */ - log_fatal("Missing 'blk' specification in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* check that the stored parity size matches the loaded state */ - if (blockmax != parity_allocated_size(state)) { - /* LCOV_EXCL_START */ - log_fatal("Internal inconsistency in parity size in '%s' at line %u\n", path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* to be backward compatible with old context files without info */ - /* create info records if missing */ - for (b = 0; b < blockmax; ++b) { - /* if the position is used */ - if (info_is_required(state, b)) { - snapraid_info info = info_get(&state->infoarr, b); - - /* if no info is present */ - if (!info) { - /* LCOV_EXCL_START */ - /* set a fake info block */ - info = info_make(save_time, 0, 0, 0); - - /* insert the info in the array */ - info_set(&state->infoarr, b, info); - /* LCOV_EXCL_STOP */ - } - } - } - - msg_verbose("%8u files\n", count_file); - msg_verbose("%8u hardlinks\n", count_hardlink); - msg_verbose("%8u symlinks\n", count_symlink); - msg_verbose("%8u empty dirs\n", count_dir); -} - -static void state_write_text(struct snapraid_state* state, STREAM* f) -{ - unsigned count_file; - unsigned count_hardlink; - unsigned count_symlink; - unsigned count_dir; - tommy_node* i; - block_off_t b; - block_off_t blockmax; - int info_has_rehash; - unsigned l; - - count_file = 0; - count_hardlink = 0; - count_symlink = 0; - count_dir = 0; - - /* blocks of all array */ - blockmax = parity_allocated_size(state); - - /* clear the info for unused blocks */ - /* and get some other info */ - info_has_rehash = 0; /* if there is a rehash info */ - for (b = 0; b < blockmax; ++b) { - /* if the position is used */ - if (position_is_required(state, b)) { - snapraid_info info = info_get(&state->infoarr, b); - - /* only if there is some info to store */ - if (info) { - if (info_get_rehash(info)) - info_has_rehash = 1; - } - } else { - /* clear any previous info */ - info_set(&state->infoarr, b, 0); - - /* and clear any deleted blocks */ - position_clear_deleted(state, b); - } - } - - sputsl("blksize ", f); - sputu32(state->block_size, f); - sputeol(f); - if (serror(f)) { - /* LCOV_EXCL_START */ - log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - if (state->hash == HASH_MURMUR3) { - sputsl("checksum murmur3", f); - } else if (state->hash == HASH_SPOOKY2) { - sputsl("checksum spooky2", f); - } else { - /* LCOV_EXCL_START */ - log_fatal("Unexpected hash when writing the content file '%s'.\n", serrorfile(f)); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - sputc(' ', f); - sputhex(state->hashseed, HASH_SIZE, f); - sputeol(f); - if (serror(f)) { - /* LCOV_EXCL_START */ - log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* previous hash only present */ - if (state->prevhash != HASH_UNDEFINED) { - /* if at least one rehash tag found, we have to save the previous hash */ - if (info_has_rehash) { - if (state->prevhash == HASH_MURMUR3) { - sputsl("prevchecksum murmur3", f); - } else if (state->prevhash == HASH_SPOOKY2) { - sputsl("prevchecksum spooky2", f); - } else { - /* LCOV_EXCL_START */ - log_fatal("Unexpected prevhash when writing the content file '%s'.\n", serrorfile(f)); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - sputc(' ', f); - sputhex(state->prevhashseed, HASH_SIZE, f); - sputeol(f); - if (serror(f)) { - /* LCOV_EXCL_START */ - log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - } - } - - /* for each map */ - for (i = state->maplist; i != 0; i = i->next) { - struct snapraid_map* map = i->data; - struct snapraid_disk* disk; - - /* find the disk for this mapping */ - disk = find_disk(state, map->name); - if (!disk) { - /* LCOV_EXCL_START */ - log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* save the mapping only for not empty disks */ - if (!disk_is_empty(disk, blockmax)) { - sputsl("mapping ", f); - sputs(map->name, f); - sputc(' ', f); - sputu32(map->position, f); - sputc(' ', f); - sputu32(map->total_blocks, f); - sputc(' ', f); - sputu32(map->free_blocks, f); - - /* if there is an uuid, print it */ - if (map->uuid[0]) { - sputc(' ', f); - sputs(map->uuid, f); - } - - sputeol(f); - if (serror(f)) { - /* LCOV_EXCL_START */ - log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* mark the disk as with mapping */ - disk->mapping_idx = 0; - } else { - /* mark the disk as without mapping */ - disk->mapping_idx = -1; - } - } - - /* for each parity */ - for (l = 0; l < state->level; ++l) { - sputsl("parity ", f); - sputu32(l, f); - sputc(' ', f); - sputu32(state->parity[l].total_blocks, f); - sputc(' ', f); - sputu32(state->parity[l].free_blocks, f); - - /* if there is an uuid, print it */ - if (state->parity[l].uuid[0]) { - sputc(' ', f); - sputs(state->parity[l].uuid, f); - } - - sputeol(f); - if (serror(f)) { - /* LCOV_EXCL_START */ - log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - } - - /* for each disk */ - for (i = state->disklist; i != 0; i = i->next) { - tommy_node* j; - struct snapraid_disk* disk = i->data; - - /* if the disk is not mapped, skip it */ - if (disk->mapping_idx < 0) - continue; - - /* for each file */ - for (j = disk->filelist; j != 0; j = j->next) { - struct snapraid_file* file = j->data; - uint64_t size; - uint64_t mtime_sec; - int32_t mtime_nsec; - uint64_t inode; - - size = file->size; - mtime_sec = file->mtime_sec; - mtime_nsec = file->mtime_nsec; - inode = file->inode; - - sputsl("file ", f); - sputs(disk->name, f); - sputc(' ', f); - sputu64(size, f); - sputc(' ', f); - sputu64(mtime_sec, f); - if (mtime_nsec != STAT_NSEC_INVALID) { - sputc('.', f); - sputu32(mtime_nsec, f); - } - sputc(' ', f); - sputu64(inode, f); - sputc(' ', f); - sputs(file->sub, f); - sputeol(f); - if (serror(f)) { - /* LCOV_EXCL_START */ - log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - /* for each block in the file */ - for (b = 0; b < file->blockmax; ++b) { - struct snapraid_block* block = &file->blockvec[b]; - unsigned block_state = block_state_get(block); - - /* consistency check */ - if (block != fs_par2block_get(disk, block->parity_pos)) { - /* LCOV_EXCL_START */ - log_fatal("Internal inconsistency mismatch for block %u state %u in file '%s'\n", block->parity_pos, block_state, file->sub); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - switch (block_state) { - case BLOCK_STATE_BLK : - sputsl("blk ", f); - break; - case BLOCK_STATE_CHG : - sputsl("chg ", f); - break; - case BLOCK_STATE_REP : - sputsl("rep ", f); - break; - default : - /* LCOV_EXCL_START */ - log_fatal("Internal inconsistency in state for block %u state %u\n", block->parity_pos, block_state); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - sputu32(block->parity_pos, f); - - sputc(' ', f); - sputhex(block->hash, HASH_SIZE, f); - - sputeol(f); - if (serror(f)) { - /* LCOV_EXCL_START */ - log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - } - - ++count_file; - } - - /* for each link */ - for (j = disk->linklist; j != 0; j = j->next) { - struct snapraid_link* link = j->data; - - switch (link_flag_get(link, FILE_IS_LINK_MASK)) { - case FILE_IS_HARDLINK : - sputsl("hardlink ", f); - ++count_hardlink; - break; - case FILE_IS_SYMLINK : - sputsl("symlink ", f); - ++count_symlink; - break; - } - - sputs(disk->name, f); - sputc(' ', f); - sputs(link->sub, f); - sputeol(f); - sputsl("to ", f); - sputs(link->linkto, f); - sputeol(f); - if (serror(f)) { - /* LCOV_EXCL_START */ - log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - } - - /* for each dir */ - for (j = disk->dirlist; j != 0; j = j->next) { - struct snapraid_dir* dir = j->data; - - sputsl("dir ", f); - sputs(disk->name, f); - sputc(' ', f); - sputs(dir->sub, f); - sputeol(f); - if (serror(f)) { - /* LCOV_EXCL_START */ - log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - ++count_dir; - } - - /* deleted blocks of the disk */ - sputsl("hole ", f); - sputs(disk->name, f); - sputeol(f); - if (serror(f)) { - /* LCOV_EXCL_START */ - log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - for (b = 0; b < blockmax; ++b) { - if (is_block_deleted(disk, b)) { - struct snapraid_block* block = fs_par2block_get(disk, b); - - /* consistency check */ - if (block->parity_pos != b) { - /* LCOV_EXCL_START */ - log_fatal("Internal inconsistency in delete position %u/%u!\n", block->parity_pos, b); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - sputsl("off ", f); - sputu32(b, f); - sputc(' ', f); - sputhex(block->hash, HASH_SIZE, f); - sputeol(f); - if (serror(f)) { - /* LCOV_EXCL_START */ - log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - } - } - } - - /* write the info for each block */ - for (b = 0; b < blockmax; ++b) { - snapraid_info info = info_get(&state->infoarr, b); - - /* 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); - } - if (info_get_justsynced(info)) { - sputsl(" justsynced", f); - } - sputeol(f); - if (serror(f)) { - /* LCOV_EXCL_START */ - log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - } - } - - if (serror(f)) { - /* LCOV_EXCL_START */ - log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } - - msg_verbose("%8u files\n", count_file); - msg_verbose("%8u hardlinks\n", count_hardlink); - msg_verbose("%8u symlinks\n", count_symlink); - msg_verbose("%8u empty dirs\n", count_dir); -} - /** * Flush the file checking the final CRC. * We exploit the fact that the CRC is always stored in the last 4 bytes. @@ -4509,10 +3040,10 @@ void state_read(struct snapraid_state* state) if (c == 'S') { state_read_binary(state, path, f); } else { - state_read_text(state, path, f, st.st_mtime); - - /* force a rewrite to convert to binary */ - state->need_write = 1; + /* LCOV_EXCL_START */ + log_fatal("The text file format is not supported anymore.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ } sclose(f); @@ -4578,10 +3109,7 @@ void state_write(struct snapraid_state* state) i = i->next; } - if (state->opt.force_content_text) - state_write_text(state, f); - else - state_write_binary(state, f); + state_write_binary(state, f); /* Use the sequence fflush() -> fsync() -> fclose() -> rename() to ensure */ /* than even in a system crash event we have one valid copy of the file. */ diff --git a/cmdline/state.h b/cmdline/state.h index 13f3a177..01ff0133 100644 --- a/cmdline/state.h +++ b/cmdline/state.h @@ -98,7 +98,6 @@ struct snapraid_option { unsigned force_scrub_at; /**< Force scrub for the specified number of blocks. */ int force_scrub_even; /**< Force scrub of all the even blocks. */ int force_content_write; /**< Force the update of the content file. */ - int force_content_text; /**< Force the use of text version of content file. */ int force_scan_winfind; /**< Force the use of FindFirst/Next in Windows to list directories. */ int force_progress; /**< Force the use of the progress status. */ unsigned force_autosave_at; /**< Force autosave at the specified block. */