Excludes handling of error condition from the coverage test.

This commit is contained in:
Andrea Mazzoleni 2014-02-03 22:40:51 +01:00
parent f0cecf55c8
commit 24fd5ab318
17 changed files with 841 additions and 5 deletions

5
TEST
View file

@ -20,6 +20,11 @@ To run a coverage test you should use:
and open the file ./cov/index.html in your browser to see the results.
Please note that in the coverage analysis we exclude the handling of all
the error conditions that result in an immediate termination of the program.
You can recognize this excluded code because it's enclosed between
the LCOV_EXCL_START and LCOV_EXCL_STOP keywords.
To test with the clang static anlayzer use:
scan-build ./configure

56
check.c
View file

@ -660,10 +660,12 @@ static int state_check_process(struct snapraid_state* state, int check, int fix,
/* close the old one, if any */
ret = handle_close(&handle[j]);
if (ret == -1) {
/* LCOV_EXCL_START */
fprintf(stderr, "DANGER! Unexpected close error in a data disk, it isn't possible to check.\n");
printf("Stopping at block %u\n", i);
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
}
/* if fixing, and the file is not excluded, we must open for writing */
@ -671,6 +673,7 @@ static int state_check_process(struct snapraid_state* state, int check, int fix,
/* if fixing, create the file, open for writing and resize if required */
ret = handle_create(&handle[j], block_file_get(block), state->opt.skip_sequential);
if (ret == -1) {
/* LCOV_EXCL_START */
if (errno == EACCES) {
fprintf(stderr, "WARNING! Please give write permission to the file.\n");
} else {
@ -679,6 +682,7 @@ static int state_check_process(struct snapraid_state* state, int check, int fix,
printf("Stopping at block %u\n", i);
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
}
/* check if the file was larger and now truncated */
@ -896,6 +900,7 @@ static int state_check_process(struct snapraid_state* state, int check, int fix,
ret = handle_write(failed[j].handle, failed[j].block, buffer[failed[j].index], state->block_size);
if (ret == -1) {
/* LCOV_EXCL_START */
/* mark the file as damaged */
file_flag_set(block_file_get(failed[j].block), FILE_IS_DAMAGED);
@ -908,6 +913,7 @@ static int state_check_process(struct snapraid_state* state, int check, int fix,
printf("Stopping at block %u\n", i);
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
}
/* if we are not sure that the recovered content is uptodate */
@ -933,11 +939,13 @@ static int state_check_process(struct snapraid_state* state, int check, int fix,
if (buffer_recov[l] == 0 && parity[l] != 0) {
ret = parity_write(parity[l], i, buffer[diskmax + l], state->block_size);
if (ret == -1) {
/* LCOV_EXCL_START */
/* we do not use DANGER because it could be ENOSPC which is not always correctly reported */
fprintf(stderr, "WARNING! Without a working %s disk, it isn't possible to fix errors on it.\n", lev_name(l));
printf("Stopping at block %u\n", i);
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
}
fprintf(stdlog, "parity_fixed:%u:%s: Fixed data error\n", i, lev_config_name(l));
@ -989,8 +997,10 @@ static int state_check_process(struct snapraid_state* state, int check, int fix,
/* A typical case is if the file is missing, */
/* and the read-only open failed before. */
if (handle[j].file != 0 && handle[j].file != file) {
/* LCOV_EXCL_START */
fprintf(stderr, "Internal inconsistency in opened file for block %u\n", block->parity_pos);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* if it isn't the last block in the file */
@ -1020,20 +1030,24 @@ static int state_check_process(struct snapraid_state* state, int check, int fix,
/* ensure to close the file before renaming */
ret = handle_close(&handle[j]);
if (ret != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error closing '%s'. %s.\n", path, strerror(errno));
fprintf(stderr, "WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
printf("Stopping at block %u\n", i);
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
}
ret = rename(path, path_to);
if (ret != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error renaming '%s' to '%s'. %s.\n", path, path_to, strerror(errno));
fprintf(stderr, "WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
printf("Stopping at block %u\n", i);
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
}
fprintf(stdlog, "status:unrecoverable:%s:%s\n", handle[j].disk->name, file->sub);
@ -1078,12 +1092,14 @@ static int state_check_process(struct snapraid_state* state, int check, int fix,
/* set the original modification time */
ret = handle_utime(&handle[j]);
if (ret == -1) {
/* LCOV_EXCL_START */
/* mark the file as damaged */
file_flag_set(file, FILE_IS_DAMAGED);
fprintf(stderr, "WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
printf("Stopping at block %u\n", i);
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
}
} else {
fprintf(stdlog, "collision:%s:%s:%s: Not setting modification time to avoid inode collision\n", handle[j].disk->name, block_file_get(block)->sub, collide_file->sub);
@ -1120,11 +1136,13 @@ close_and_continue:
/* ensure to close the file just after finishing with it */
ret = handle_close(&handle[j]);
if (ret != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error closing '%s'. %s.\n", path, strerror(errno));
fprintf(stderr, "WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
printf("Stopping at block %u\n", i);
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
}
}
@ -1133,7 +1151,9 @@ close_and_continue:
/* progress */
if (state_progress(state, i, countpos, countmax, countsize)) {
/* LCOV_EXCL_START */
break;
/* LCOV_EXCL_STOP */
}
}
@ -1194,16 +1214,19 @@ close_and_continue:
/* create the ancestor directories */
ret = mkancestor(path);
if (ret != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
printf("Stopping\n");
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
}
/* create it */
/* O_NOFOLLOW: do not follow links to ensure to open the real file */
f = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_NOFOLLOW, 0600);
if (f == -1) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error creating empty file '%s'. %s.\n", path, strerror(errno));
if (errno == EACCES) {
fprintf(stderr, "WARNING! Please give write permission to the file.\n");
@ -1214,26 +1237,31 @@ close_and_continue:
printf("Stopping\n");
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
}
/* set the original modification time */
ret = file_utime(file, f);
if (ret != 0) {
/* LCOV_EXCL_START */
close(f);
fprintf(stderr, "WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
printf("Stopping\n");
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
}
/* close it */
ret = close(f);
if (ret != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
printf("Stopping\n");
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
}
fprintf(stdlog, "fixed:%s:%s: Fixed empty file\n", disk->name, file->sub);
@ -1351,26 +1379,31 @@ close_and_continue:
/* create the ancestor directories */
ret = mkancestor(path);
if (ret != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
printf("Stopping\n");
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
}
/* if it exists, it must be deleted before recreating */
ret = remove(path);
if (ret != 0 && errno != ENOENT) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error removing '%s'. %s.\n", path, strerror(errno));
fprintf(stderr, "WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
printf("Stopping\n");
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
}
/* create it */
if (link_flag_has(link, FILE_IS_HARDLINK)) {
ret = hardlink(pathto, path);
if (ret != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error writing hardlink '%s' to '%s'. %s.\n", path, pathto, strerror(errno));
if (errno == EACCES) {
fprintf(stderr, "WARNING! Please give write permission to the hardlink.\n");
@ -1381,6 +1414,7 @@ close_and_continue:
printf("Stopping\n");
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
}
fprintf(stdlog, "hardlinkfixed:%s:%s: Fixed hardlink error\n", disk->name, link->sub);
@ -1388,6 +1422,7 @@ close_and_continue:
} else {
ret = symlink(link->linkto, path);
if (ret != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error writing symlink '%s' to '%s'. %s.\n", path, link->linkto, strerror(errno));
if (errno == EACCES) {
fprintf(stderr, "WARNING! Please give write permission to the symlink.\n");
@ -1398,6 +1433,7 @@ close_and_continue:
printf("Stopping\n");
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
}
fprintf(stdlog, "symlinkfixed:%s:%s: Fixed symlink error\n", disk->name, link->sub);
@ -1448,15 +1484,18 @@ close_and_continue:
/* create the ancestor directories */
ret = mkancestor(path);
if (ret != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
printf("Stopping\n");
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
}
/* create it */
ret = mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
if (ret != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error creating dir '%s'. %s.\n", path, strerror(errno));
if (errno == EACCES) {
fprintf(stderr, "WARNING! Please give write permission to the dir.\n");
@ -1467,6 +1506,7 @@ close_and_continue:
printf("Stopping\n");
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
}
fprintf(stdlog, "dir_fixed:%s:%s: Fixed dir error\n", disk->name, dir->sub);
@ -1487,9 +1527,11 @@ bail:
for(j=0;j<diskmax;++j) {
ret = handle_close(&handle[j]);
if (ret == -1) {
/* LCOV_EXCL_START */
fprintf(stderr, "DANGER! Unexpected close error in a data disk.\n");
++unrecoverable_error;
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */
}
}
@ -1533,10 +1575,12 @@ bail:
ret = remove(path);
if (ret != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error removing '%s'. %s.\n", path, strerror(errno));
fprintf(stderr, "WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
++unrecoverable_error;
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */
}
}
}
@ -1636,16 +1680,20 @@ int state_check(struct snapraid_state* state, int check, int fix, block_off_t bl
printf("Initializing...\n");
if (!check && fix) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error in calling, you cannot fix without checking parity.\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
blockmax = parity_size(state);
size = blockmax * (data_off_t)state->block_size;
if (blockstart > blockmax) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error in the specified starting block %u. It's bigger than the parity size %u.\n", blockstart, blockmax);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* adjust the number of block to process */
@ -1660,14 +1708,18 @@ int state_check(struct snapraid_state* state, int check, int fix, block_off_t bl
parity_ptr[l] = &parity[l];
ret = parity_create(parity_ptr[l], state->parity_path[l], &out_size, state->opt.skip_sequential);
if (ret == -1) {
/* LCOV_EXCL_START */
fprintf(stderr, "WARNING! Without an accessible %s file, it isn't possible to fix any error.\n", lev_name(l));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
ret = parity_chsize(parity_ptr[l], size, &out_size, state->opt.skip_fallocate);
if (ret == -1) {
/* LCOV_EXCL_START */
fprintf(stderr, "WARNING! Without an accessible %s file, it isn't possible to sync.\n", lev_name(l));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
} else if (check) {
@ -1701,8 +1753,10 @@ int state_check(struct snapraid_state* state, int check, int fix, block_off_t bl
if (blockstart < blockmax) {
ret = state_check_process(state, check, fix, parity_ptr, blockstart, blockmax);
if (ret == -1) {
/* LCOV_EXCL_START */
++error;
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */
}
}
@ -1710,11 +1764,13 @@ int state_check(struct snapraid_state* state, int check, int fix, block_off_t bl
for(l=0;l<state->level;++l) {
if (parity_ptr[l]) {
ret = parity_close(parity_ptr[l]);
/* LCOV_EXCL_START */
if (ret == -1) {
fprintf(stderr, "DANGER! Unexpected close error in %s disk.\n", lev_name(l));
++error;
/* continue, as we are already exiting */
}
/* LCOV_EXCL_STOP */
}
}

19
dry.c
View file

@ -71,19 +71,23 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit
/* close the old one, if any */
ret = handle_close(&handle[j]);
if (ret == -1) {
/* LCOV_EXCL_START */
fprintf(stderr, "DANGER! Unexpected close error in a data disk, it isn't possible to dry.\n");
printf("Stopping at block %u\n", i);
++error;
goto bail;
/* LCOV_EXCL_STOP */
}
/* open the file only for reading */
ret = handle_open(&handle[j], block_file_get(block), state->opt.skip_sequential, stdlog);
if (ret == -1) {
/* LCOV_EXCL_START */
fprintf(stderr, "DANGER! Unexpected open error in a data disk, it isn't possible to dry.\n");
printf("Stopping at block %u\n", i);
++error;
goto bail;
/* LCOV_EXCL_STOP */
}
}
@ -114,7 +118,9 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit
/* progress */
if (state_progress(state, i, countpos, countmax, countsize)) {
/* LCOV_EXCL_START */
break;
/* LCOV_EXCL_STOP */
}
}
@ -125,9 +131,11 @@ bail:
for(j=0;j<diskmax;++j) {
ret = handle_close(&handle[j]);
if (ret == -1) {
/* LCOV_EXCL_START */
fprintf(stderr, "DANGER! Unexpected close error in a data disk.\n");
++error;
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */
}
}
@ -159,8 +167,10 @@ void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t
blockmax = parity_size(state);
if (blockstart > blockmax) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error in the specified starting block %u. It's bigger than the parity size %u.\n", blockstart, blockmax);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* adjust the number of block to process */
@ -186,8 +196,10 @@ void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t
if (blockstart < blockmax) {
ret = state_dry_process(state, parity_ptr, blockstart, blockmax);
if (ret == -1) {
/* LCOV_EXCL_START */
++error;
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */
}
}
@ -196,14 +208,19 @@ void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t
if (parity_ptr[l]) {
ret = parity_close(parity_ptr[l]);
if (ret == -1) {
/* LCOV_EXCL_START */
++error;
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */
}
}
}
/* abort if required */
if (error != 0)
if (error != 0) {
/* LCOV_EXCL_START */
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}

6
elem.c
View file

@ -244,8 +244,10 @@ int filter_existence(int filter_missing, const char* dir, const char* sub)
/* if the file doesn't exist, we don't filter it out */
if (errno == ENOENT)
return 0;
/* LCOV_EXCL_START */
fprintf(stderr, "Error in stat file '%s'. %s.\n", path, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* the file is present, so we filter it out */
@ -302,8 +304,10 @@ block_off_t block_file_pos(struct snapraid_block* block)
struct snapraid_file* file = block_file_get(block);
if (block < file->blockvec || block >= file->blockvec + file->blockmax) {
/* LCOV_EXCL_START */
fprintf(stderr, "Internal inconsistency in block %u ownership\n", block->parity_pos);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
return block - file->blockvec;
@ -599,8 +603,10 @@ int disk_is_empty(struct snapraid_disk* disk, block_off_t blockmax)
/* if there is a deleted block, the disk is not empty */
return 0;
default:
/* LCOV_EXCL_START */
fprintf(stderr, "Internal inconsistency for used block in disk '%s' without files\n", disk->name);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}

4
elem.h
View file

@ -440,8 +440,10 @@ static inline void block_file_set(struct snapraid_block* block, struct snapraid_
/* ensure that the pointer doesn't use the flag space */
if ((ptr & (uintptr_t)BLOCK_STATE_MASK) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Internal error for pointer not aligned\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
block->file_mixed = (block->file_mixed & ~(uintptr_t)BLOCK_STATE_MASK) | ptr;
@ -465,8 +467,10 @@ static inline void block_state_set(struct snapraid_block* block, unsigned state)
{
/* ensure that the state can be stored inside the file pointer */
if ((state & BLOCK_STATE_MASK) != state) {
/* LCOV_EXCL_START */
fprintf(stderr, "Internal error when setting the block state %u\n", state);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
block->file_mixed &= ~(uintptr_t)BLOCK_STATE_MASK;

View file

@ -428,9 +428,10 @@ struct snapraid_handle* handle_map(struct snapraid_state* state, unsigned* handl
break;
}
if (k==0) {
fprintf(stderr, "Inconsistent disk mapping.\n");
/* LCOV_EXCL_START */
fprintf(stderr, "Internal error for inconsistent disk mapping.\n");
exit(EXIT_FAILURE);
continue;
/* LCOV_EXCL_STOP */
}
handle[map->position].disk = disk;

View file

@ -74,8 +74,10 @@ static void import_file(struct snapraid_state* state, const char* path, uint64_t
flags |= O_SEQUENTIAL;
f = open(path, flags);
if (f == -1) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error opening file '%s'. %s.\n", path, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
#if HAVE_POSIX_FADVISE
@ -83,8 +85,10 @@ static void import_file(struct snapraid_state* state, const char* path, uint64_t
/* advise sequential access */
ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL);
if (ret != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error advising file '%s'. %s.\n", path, strerror(ret));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
#endif
@ -98,8 +102,10 @@ static void import_file(struct snapraid_state* state, const char* path, uint64_t
ret = read(f, buffer, read_size);
if (ret < 0 || (unsigned)ret != read_size) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error reading file '%s'. %s.\n", path, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
block->file = file;
@ -122,8 +128,10 @@ static void import_file(struct snapraid_state* state, const char* path, uint64_t
ret = close(f);
if (ret != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error closing file '%s'. %s.\n", path, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
tommy_list_insert_tail(&state->importlist, &file->nodelist, file);
@ -161,25 +169,33 @@ int state_import_fetch(struct snapraid_state* state, int rehash, const unsigned
f = open(path, O_RDONLY | O_BINARY);
if (f == -1) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error opening file '%s'. %s.\n", path, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (lseek(f, block->offset, SEEK_SET) != block->offset) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error seeking file '%s'. %s.\n", path, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
ret = read(f, buffer, read_size);
if (ret < 0 || (unsigned)ret != read_size) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error reading file '%s'. %s.\n", path, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
ret = close(f);
if (ret != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error closing file '%s'. %s.\n", path, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (read_size != block_size) {
@ -194,9 +210,11 @@ int state_import_fetch(struct snapraid_state* state, int rehash, const unsigned
memhash(state->hash, state->hashseed, buffer_hash, buffer, read_size);
if (memcmp(buffer_hash, hash, HASH_SIZE) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error in data reading file '%s'.\n", path);
fprintf(stderr, "Please don't change imported files while running.\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
return 0;
@ -208,8 +226,10 @@ static void import_dir(struct snapraid_state* state, const char* dir)
d = opendir(dir);
if (!d) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error opening directory '%s'. %s.\n", dir, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
while (1) {
@ -222,8 +242,10 @@ static void import_dir(struct snapraid_state* state, const char* dir)
errno = 0;
dd = readdir(d);
if (dd == 0 && errno != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error reading directory '%s'. %s.\n", dir, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (dd == 0) {
break; /* finished */
@ -244,8 +266,10 @@ static void import_dir(struct snapraid_state* state, const char* dir)
#else
/* get lstat info about the file */
if (lstat(path, &st) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error in stat file/directory '%s'. %s.\n", path, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
#endif
@ -257,8 +281,10 @@ static void import_dir(struct snapraid_state* state, const char* dir)
}
if (closedir(d) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error closing directory '%s'. %s.\n", dir, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}

2
list.c
View file

@ -92,7 +92,9 @@ void state_list(struct snapraid_state* state)
case FILE_IS_SYMLINK : type = "symlink"; break;
case FILE_IS_SYMDIR : type = "symdir"; break;
case FILE_IS_JUNCTION : type = "junction"; break;
/* LCOV_EXCL_START */
default: type = "unknown"; break;
/* LCOV_EXCL_STOP */
}
++link_count;

View file

@ -58,8 +58,10 @@ void create_file(const char* path, int size)
/* remove the existing file if any */
if (remove(path) != 0) {
if (errno != ENOENT) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error removing file %s\n", path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
} else {
/* don't recreate a 0 file to avoid ZERO protection */
@ -68,8 +70,10 @@ void create_file(const char* path, int size)
f = fopen(path, "wb");
if (!f) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error writing file %s\n", path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
count = size;
@ -92,14 +96,18 @@ void create_symlink(const char* path, const char* linkto)
/* remove the existing file if any */
if (remove(path) != 0) {
if (errno != ENOENT) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error removing file %s\n", path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
if (symlink(linkto, path) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error writing symlink %s\n", path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
@ -118,8 +126,10 @@ void generate(int disk, int size)
/* create it */
if (mkdir(path, 0777) != 0) {
if (errno != EEXIST) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error creating directory %s\n", path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
@ -205,8 +215,10 @@ void fallback(int f, struct stat* st)
#error No function available to set file timestamps
#endif
if (ret != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error restoring time\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
@ -232,8 +244,10 @@ void writ(const char* path, int size, int silent_error)
if (lstat(path, &st) != 0) {
if (errno == ENOENT)
return; /* it may be already deleted */
/* LCOV_EXCL_START */
fprintf(stderr, "Error accessing %s\n", path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (S_ISREG(st.st_mode)) {
@ -244,8 +258,10 @@ void writ(const char* path, int size, int silent_error)
f = fopen(path, "r+b");
if (!f) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error writing %s\n", path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* start at random position inside the file */
@ -254,8 +270,10 @@ void writ(const char* path, int size, int silent_error)
else
start = 0;
if (fseek(f, start, SEEK_SET) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error seeking %s\n", path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* write garbage, in case also over the end */
@ -286,8 +304,10 @@ void append(const char* path, int size)
if (lstat(path, &st) != 0) {
if (errno == ENOENT)
return; /* it may be already deleted */
/* LCOV_EXCL_START */
fprintf(stderr, "Error accessing %s\n", path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (S_ISREG(st.st_mode)) {
@ -296,8 +316,10 @@ void append(const char* path, int size)
f = fopen(path, "ab");
if (!f) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error appending %s\n", path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* write garbage, in case also over the end */
@ -321,8 +343,10 @@ void truncat(const char* path, int size)
if (lstat(path, &st) != 0) {
if (errno == ENOENT)
return; /* it may be already deleted */
/* LCOV_EXCL_START */
fprintf(stderr, "Error accessing %s\n", path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (S_ISREG(st.st_mode)) {
@ -332,8 +356,10 @@ void truncat(const char* path, int size)
f = fopen(path, "r+b");
if (!f) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error writing %s\n", path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* truncate at random position inside the file */
@ -347,8 +373,10 @@ void truncat(const char* path, int size)
start = 1;
if (ftruncate(fileno(f), start) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error truncating %s\n", path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
fclose(f);
@ -365,8 +393,10 @@ void change(const char* path, int size)
if (lstat(path, &st) != 0) {
if (errno == ENOENT)
return; /* it may be already deleted */
/* LCOV_EXCL_START */
fprintf(stderr, "Error accessing %s\n", path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (S_ISLNK(st.st_mode)) {
@ -374,16 +404,20 @@ void change(const char* path, int size)
if (rnd(2) == 0) {
/* delete */
if (remove(path) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error removing %s\n", path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
} else {
/* recreate */
char linkto[PATH_MAX];
if (remove(path) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error removing %s\n", path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
rnd_name(linkto);
@ -407,8 +441,10 @@ void change(const char* path, int size)
} else {
/* delete */
if (remove(path) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error removing %s\n", path);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
}
@ -436,16 +472,20 @@ int main(int argc, char* argv[])
int i, j, b;
if (argc < 2) {
/* LCOV_EXCL_START */
help();
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (strcmp(argv[1], "generate") == 0) {
int disk, file, size;
if (argc != 6) {
/* LCOV_EXCL_START */
help();
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
seed = atoi(argv[2]);
@ -468,8 +508,10 @@ int main(int argc, char* argv[])
int silent_error = strcmp(argv[1], "damage") == 0;
if (argc < 6) {
/* LCOV_EXCL_START */
help();
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
seed = atoi(argv[2]);
@ -489,8 +531,10 @@ int main(int argc, char* argv[])
int size;
if (argc < 5) {
/* LCOV_EXCL_START */
help();
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
seed = atoi(argv[2]);
@ -507,8 +551,10 @@ int main(int argc, char* argv[])
int size;
if (argc < 5) {
/* LCOV_EXCL_START */
help();
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
seed = atoi(argv[2]);
@ -525,8 +571,10 @@ int main(int argc, char* argv[])
int size;
if (argc < 5) {
/* LCOV_EXCL_START */
help();
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
seed = atoi(argv[2]);
@ -540,8 +588,10 @@ int main(int argc, char* argv[])
change(argv[i], rnd(size));
}
} else {
/* LCOV_EXCL_START */
help();
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
return 0;

20
pool.c
View file

@ -32,8 +32,10 @@ static int clean_dir(struct snapraid_state* state, const char* dir)
d = opendir(dir);
if (!d) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error opening pool directory '%s'. %s.\n", dir, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
while (1) {
@ -46,8 +48,10 @@ static int clean_dir(struct snapraid_state* state, const char* dir)
errno = 0;
dd = readdir(d);
if (dd == 0 && errno != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error reading pool directory '%s'. %s.\n", dir, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (dd == 0 && errno == 0) {
break; /* finished */
@ -66,8 +70,10 @@ static int clean_dir(struct snapraid_state* state, const char* dir)
#else
/* get lstat info about the file */
if (lstat(path_next, &st) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
#endif
@ -77,8 +83,10 @@ static int clean_dir(struct snapraid_state* state, const char* dir)
/* delete the link */
ret = remove(path_next);
if (ret < 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error removing symlink '%s'. %s.\n", path_next, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
} else if (S_ISDIR(st.st_mode)) {
/* recurse */
@ -99,8 +107,10 @@ static int clean_dir(struct snapraid_state* state, const char* dir)
} else
#endif
{
/* LCOV_EXCL_START */
fprintf(stderr, "Error removing pool directory '%s'. %s.\n", path_next, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
} else {
@ -116,8 +126,10 @@ static int clean_dir(struct snapraid_state* state, const char* dir)
}
if (closedir(d) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error closing pool directory '%s'. %s.\n", dir, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
return ignored;
@ -148,7 +160,9 @@ static void make_link(const char* pool_dir, const char* share_dir, struct snapra
/* create the ancestor directories */
ret = mkancestor(path);
if (ret != 0) {
/* LCOV_EXCL_START */
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* convert back slashes */
@ -161,12 +175,16 @@ static void make_link(const char* pool_dir, const char* share_dir, struct snapra
fprintf(stderr, "WARNING! Duplicate pooling for '%s'\n", path);
#ifdef _WIN32
} else if (errno == EPERM) {
/* LCOV_EXCL_START */
fprintf(stderr, "You must run as Adminstrator to be able to create symlinks.\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
#endif
} else {
/* LCOV_EXCL_START */
fprintf(stderr, "Error writing symlink '%s'. %s.\n", path, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
}
@ -179,8 +197,10 @@ void state_pool(struct snapraid_state* state)
unsigned count;
if (state->pool[0] == 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "To use the 'pool' command you must set the pool directory in the configuration file\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
printf("Cleaning...\n");

View file

@ -37,13 +37,17 @@ void state_rehash(struct snapraid_state* state)
/* check if a rehash is already in progress */
if (state->prevhash != HASH_UNDEFINED) {
/* LCOV_EXCL_START */
fprintf(stderr, "You already have a rehash in progress.\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (state->hash == state->besthash) {
/* LCOV_EXCL_START */
fprintf(stderr, "You are already using the best hash for your platform.\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* copy the present hash as previous one */
@ -66,8 +70,10 @@ void state_rehash(struct snapraid_state* state)
}
if (info_get_rehash(info)) {
/* LCOV_EXCL_START */
fprintf(stderr, "Internal inconsistency for a rehash already in progress\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* enable the rehash */

37
scan.c
View file

@ -81,8 +81,10 @@ static void scan_link(struct snapraid_scan* scan, struct snapraid_state* state,
if (link) {
/* check if multiple files have the same name */
if (link_flag_has(link, FILE_IS_PRESENT)) {
/* LCOV_EXCL_START */
fprintf(stderr, "Internal inconsistency for link '%s%s'\n", disk->dir, sub);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* mark as present */
@ -195,8 +197,10 @@ static void scan_file_deallocate(struct snapraid_state* state, struct snapraid_d
hash_invalid_set(deleted->block.hash);
break;
default:
/* LCOV_EXCL_START */
fprintf(stderr, "Internal state inconsistency in scanning for block %u state %u\n", block->parity_pos, block_state);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* insert it in the list of deleted blocks */
@ -430,8 +434,10 @@ static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state,
scan_link(scan, state, output, disk, sub, file->sub, FILE_IS_HARDLINK);
return;
} else {
/* LCOV_EXCL_START */
fprintf(stderr, "Internal inode '%"PRIu64"' inconsistency for file '%s%s' already present\n", (uint64_t)st->st_ino, disk->dir, sub);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
@ -492,8 +498,10 @@ static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state,
/* for sure it cannot be already present */
if (file_flag_has(file, FILE_IS_PRESENT)) {
/* LCOV_EXCL_START */
fprintf(stderr, "Internal inode '%"PRIu64"' inconsistency for files '%s%s' and '%s%s' matching and already present but different\n", file->inode, disk->dir, sub, disk->dir, file->sub);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* assume a previously used inode, it's the worst case */
@ -532,16 +540,19 @@ static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state,
} else {
/* here the inode has to be different, otherwise we would have found it before */
if (file->inode == st->st_ino) {
/* LCOV_EXCL_START */
fprintf(stderr, "Internal inode '%"PRIu64"' inconsistency for files '%s%s' as unexpected matching\n", file->inode, disk->dir, sub);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
/* for sure it cannot be already present */
if (file_flag_has(file, FILE_IS_PRESENT)) {
/* LCOV_EXCL_START */
fprintf(stderr, "Internal path inconsistency for file '%s%s' matching and already present\n", disk->dir, sub);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* check if the file is not changed */
@ -617,11 +628,13 @@ static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state,
/* the size of a file after a crash doesn't propagate to the backup */
if (file->size != 0 && st->st_size == 0) {
if (!state->opt.force_zero) {
/* LCOV_EXCL_START */
fprintf(stderr, "The file '%s%s' has unexpected zero size! If this an expected state\n", disk->dir, sub);
fprintf(stderr, "you can '%s' anyway usinge 'snapraid --force-zero %s'\n", state->command, state->command);
fprintf(stderr, "Instead, it's possible that after a kernel crash this file was lost,\n");
fprintf(stderr, "and you can use 'snapraid --filter %s fix' to recover it.\n", sub);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
@ -707,8 +720,10 @@ static void scan_emptydir(struct snapraid_scan* scan, struct snapraid_disk* disk
if (dir) {
/* check if multiple files have the same name */
if (dir_flag_has(dir, FILE_IS_PRESENT)) {
/* LCOV_EXCL_START */
fprintf(stderr, "Internal inconsistency for dir '%s%s'\n", disk->dir, sub);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* mark as present */
@ -775,8 +790,10 @@ struct stat* dstat(struct dirent_sorted* dd)
struct stat* dstat(const char* file, struct stat* st)
{
if (lstat(file, st) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error in stat file/directory '%s'. %s.\n", file, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
return st;
}
@ -797,9 +814,11 @@ static int scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, in
d = opendir(dir);
if (!d) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error opening directory '%s'. %s.\n", dir, strerror(errno));
fprintf(stderr, "You can exclude it in the config file with:\n\texclude /%s\n", sub);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* read the full directory */
@ -815,9 +834,11 @@ static int scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, in
errno = 0;
dd = readdir(d);
if (dd == 0 && errno != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error reading directory '%s'. %s.\n", dir, strerror(errno));
fprintf(stderr, "You can exclude it in the config file with:\n\texclude /%s\n", sub);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (dd == 0) {
break; /* finished */
@ -833,8 +854,10 @@ static int scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, in
/* check for not supported file names */
if (name[0] == 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Unsupported name '%s' in file '%s'.\n", name, path_next);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* exclude hidden files even before calling lstat() */
@ -874,8 +897,10 @@ static int scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, in
}
if (closedir(d) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error closing directory '%s'. %s.\n", dir, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
#if HAVE_STRUCT_DIRENT_D_INO
@ -943,14 +968,18 @@ static int scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, in
/* get inode info about the file, Windows needs an additional step */
/* also for hardlink, the real size of the file is read here */
if (lstat_ex(path_next, st) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error in stat_inode file '%s'. %s.\n", path_next, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
#endif
if (state->opt.force_order == SORT_PHYSICAL) {
if (filephy(path_next, st, &physical) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error in getting the physical offset of file '%s'. %s.\n", path_next, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
} else {
physical = 0;
@ -970,12 +999,16 @@ static int scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, in
ret = readlink(path_next, subnew, sizeof(subnew));
if (ret >= PATH_MAX) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error in readlink file '%s'. Symlink too long.\n", path_next);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (ret < 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error in readlink file '%s'. %s.\n", path_next, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* readlink doesn't put the final 0 */
@ -1084,8 +1117,10 @@ void state_scan(struct snapraid_state* state, int output)
/* check if the disk supports persistent inodes */
ret = fsinfo(disk->dir, &has_persistent_inode);
if (ret < 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error accessing disk '%s' to get filesystem info. %s.\n", disk->dir, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (!has_persistent_inode) {
disk->has_volatile_inodes = 1;

12
scrub.c
View file

@ -232,6 +232,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
struct snapraid_file* file = handle[j].file;
ret = handle_close(&handle[j]);
if (ret == -1) {
/* LCOV_EXCL_START */
/* This one is really an unexpected error, because we are only reading */
/* and closing a descriptor should never fail */
fprintf(stdlog, "error:%u:%s:%s: Close error. %s\n", i, handle[j].disk->name, file->sub, strerror(errno));
@ -239,6 +240,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
printf("Stopping at block %u\n", i);
++error;
goto bail;
/* LCOV_EXCL_STOP */
}
}
@ -384,7 +386,9 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
/* progress */
if (state_progress(state, i, countpos, countmax, countsize)) {
/* LCOV_EXCL_START */
break;
/* LCOV_EXCL_STOP */
}
/* autosave */
@ -428,9 +432,11 @@ bail:
for(j=0;j<diskmax;++j) {
ret = handle_close(&handle[j]);
if (ret == -1) {
/* LCOV_EXCL_START */
fprintf(stderr, "DANGER! Unexpected close error in a data disk.\n");
++error;
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */
}
}
@ -515,8 +521,10 @@ int state_scrub(struct snapraid_state* state, int percentage, int olderthan)
}
if (!count) {
/* LCOV_EXCL_START */
fprintf(stderr, "The array appears to be empty.\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* sort it */
@ -547,8 +555,10 @@ int state_scrub(struct snapraid_state* state, int percentage, int olderthan)
parity_ptr[l] = &parity[l];
ret = parity_open(parity_ptr[l], state->parity_path[l], state->opt.skip_sequential);
if (ret == -1) {
/* LCOV_EXCL_START */
fprintf(stderr, "WARNING! Without an accessible %s file, it isn't possible to scrub.\n", lev_name(l));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
@ -565,9 +575,11 @@ int state_scrub(struct snapraid_state* state, int percentage, int olderthan)
for(l=0;l<state->level;++l) {
ret = parity_close(parity_ptr[l]);
if (ret == -1) {
/* LCOV_EXCL_START */
fprintf(stderr, "DANGER! Unexpected close error in %s disk.\n", lev_name(l));
++error;
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */
}
}

View file

@ -84,8 +84,10 @@ static void test_hash(void)
memcpy(buffer_aligned, TEST_MURMUR3[i].data, TEST_MURMUR3[i].len);
memhash(HASH_MURMUR3, seed_aligned, digest, buffer_aligned, TEST_MURMUR3[i].len);
if (memcmp(digest, TEST_MURMUR3[i].digest, HASH_SIZE) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Failed Murmur3 test\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
@ -94,8 +96,10 @@ static void test_hash(void)
memcpy(buffer_aligned, TEST_SPOOKY2[i].data, TEST_SPOOKY2[i].len);
memhash(HASH_SPOOKY2, seed_aligned, digest, buffer_aligned, TEST_SPOOKY2[i].len);
if (memcmp(digest, TEST_SPOOKY2[i].digest, HASH_SIZE) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Failed Spooky2 test\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
@ -141,8 +145,10 @@ static void test_crc32c(void)
uint32_t digest;
digest = crc32c(0, (const unsigned char*)TEST_CRC32C[i].data, TEST_CRC32C[i].len);
if (digest != TEST_CRC32C[i].digest) {
/* LCOV_EXCL_START */
fprintf(stderr, "Failed CRC32C test\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
}
@ -156,47 +162,67 @@ void selftest(void)
/* large file check */
if (sizeof(off_t) < sizeof(uint64_t)) {
/* LCOV_EXCL_START */
fprintf(stderr, "Missing support for large files\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
test_hash();
test_crc32c();
if (raid_selftest() != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Failed SELF test\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (raid_test_sort() != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Failed SORT test\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (raid_test_insert() != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Failed INSERT test\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (raid_test_combo() != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Failed COMBO test\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (raid_test_par(RAID_MODE_VANDERMONDE, 32, 256) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Failed GEN Vandermonde test\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (raid_test_rec(RAID_MODE_VANDERMONDE, 12, 256) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Failed REC Vandermonde test\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (raid_test_par(RAID_MODE_CAUCHY, 32, 256) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Failed GEN Cauchy test\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (raid_test_rec(RAID_MODE_CAUCHY, 12, 256) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Failed REC Cauchy test\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (raid_test_par(RAID_MODE_CAUCHY, 1, 256) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Failed GEN Cauchy test sigle data disk\n");
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}

View file

@ -197,6 +197,7 @@ struct option long_options[] = {
volatile int global_interrupt = 0;
/* LCOV_EXCL_START */
void signal_handler(int signal)
{
switch (signal) {
@ -205,6 +206,7 @@ void signal_handler(int signal)
break;
}
}
/* LCOV_EXCL_STOP */
#define OPERATION_DIFF 0
#define OPERATION_SYNC 1
@ -281,16 +283,20 @@ int main(int argc, char* argv[])
case 'f' : {
struct snapraid_filter* filter = filter_alloc_file(1, optarg);
if (!filter) {
/* LCOV_EXCL_START */
fprintf(stderr, "Invalid filter specification '%s'\n", optarg);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
tommy_list_insert_tail(&filterlist_file, &filter->node, filter);
} break;
case 'd' : {
struct snapraid_filter* filter = filter_alloc_disk(1, optarg);
if (!filter) {
/* LCOV_EXCL_START */
fprintf(stderr, "Invalid filter specification '%s'\n", optarg);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
tommy_list_insert_tail(&filterlist_disk, &filter->node, filter);
} break;
@ -303,42 +309,54 @@ int main(int argc, char* argv[])
case 'p' :
percentage = strtoul(optarg, &e, 10);
if (!e || *e || percentage > 100) {
/* LCOV_EXCL_START */
fprintf(stderr, "Invalid percentage '%s'\n", optarg);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
break;
case 'o' :
olderthan = strtoul(optarg, &e, 10);
if (!e || *e || olderthan > 1000) {
/* LCOV_EXCL_START */
fprintf(stderr, "Invalid number of days '%s'\n", optarg);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
break;
case 's' :
blockstart = strtoul(optarg, &e, 0);
if (!e || *e) {
/* LCOV_EXCL_START */
fprintf(stderr, "Invalid start position '%s'\n", optarg);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
break;
case 't' :
blockcount = strtoul(optarg, &e, 0);
if (!e || *e) {
/* LCOV_EXCL_START */
fprintf(stderr, "Invalid count number '%s'\n", optarg);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
break;
case 'i' :
if (import) {
/* LCOV_EXCL_START */
fprintf(stderr, "Import directory '%s' already specified as '%s'\n", optarg, import);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
import = optarg;
break;
case 'l' :
if (log) {
/* LCOV_EXCL_START */
fprintf(stderr, "Log file '%s' already specified as '%s'\n", optarg, log);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
log = optarg;
break;
@ -443,8 +461,10 @@ int main(int argc, char* argv[])
opt.rawsync = 1;
break;
default:
/* LCOV_EXCL_START */
fprintf(stderr, "Unknown option '%c'\n", (char)c);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
@ -485,8 +505,10 @@ int main(int argc, char* argv[])
} else if (strcmp(argv[optind], "test-rewrite") == 0) {
operation = OPERATION_REWRITE;
} else {
/* LCOV_EXCL_START */
fprintf(stderr, "Unknown command '%s'\n", argv[optind]);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* check options compatibility */
@ -495,8 +517,10 @@ int main(int argc, char* argv[])
break;
default:
if (audit_only) {
/* LCOV_EXCL_START */
fprintf(stderr, "You cannot use -A, --audit-only with the '%s' command\n", command);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
@ -507,16 +531,22 @@ int main(int argc, char* argv[])
break;
default:
if (!tommy_list_empty(&filterlist_file)) {
/* LCOV_EXCL_START */
fprintf(stderr, "You cannot use -f, --filter with the '%s' command\n", command);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (!tommy_list_empty(&filterlist_disk)) {
/* LCOV_EXCL_START */
fprintf(stderr, "You cannot use -d, --filter-disk with the '%s' command\n", command);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
if (filter_missing != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "You cannot use -m, --filter-missing with the '%s' command\n", command);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
@ -526,8 +556,10 @@ int main(int argc, char* argv[])
break;
default:
if (filter_error != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "You cannot use -e, --filter-error with the '%s' command\n", command);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
@ -537,8 +569,10 @@ int main(int argc, char* argv[])
break;
default:
if (import != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "You cannot import with the '%s' command\n", command);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
@ -557,8 +591,10 @@ int main(int argc, char* argv[])
} else {
stdlog = fopen(log, "wt");
if (!stdlog) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error opening the log file '%s'. %s.\n", log, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
@ -578,6 +614,7 @@ int main(int argc, char* argv[])
if (!opt.skip_lock) {
lock = lock_lock(state.lockfile);
if (lock == -1) {
/* LCOV_EXCL_START */
if (errno != EWOULDBLOCK) {
fprintf(stderr, "Error creating the lock file '%s'. %s.\n", state.lockfile, strerror(errno));
} else {
@ -585,6 +622,7 @@ int main(int argc, char* argv[])
fprintf(stderr, "SnapRAID is already in use!\n");
}
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
#else
@ -648,7 +686,7 @@ int main(int argc, char* argv[])
state_write(&state);
/* abort if required */
if (ret == -1)
if (ret != 0)
exit(EXIT_FAILURE);
} else if (operation == OPERATION_DRY) {
state_read(&state);
@ -742,16 +780,20 @@ int main(int argc, char* argv[])
/* close log file */
if (stdlog != stdout && stdlog != stderr) {
if (fclose(stdlog) != 0) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error closing the log file '%s'. %s.\n", log, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
#if HAVE_LOCKFILE
if (!opt.skip_lock) {
if (lock_unlock(lock) == -1) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error closing the lock file '%s'. %s.\n", state.lockfile, strerror(errno));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
#endif

492
state.c

File diff suppressed because it is too large Load diff

36
sync.c
View file

@ -119,6 +119,7 @@ static void state_hash_process(struct snapraid_state* state, block_off_t blockst
struct snapraid_file* file = handle[j].file;
ret = handle_close(&handle[j]);
if (ret == -1) {
/* LCOV_EXCL_START */
/* This one is really an unexpected error, because we are only reading */
/* and closing a descriptor should never fail */
fprintf(stdlog, "error:%u:%s:%s: Close error. %s\n", i, handle[j].disk->name, file->sub, strerror(errno));
@ -127,6 +128,7 @@ static void state_hash_process(struct snapraid_state* state, block_off_t blockst
printf("Stopping at block %u\n", i);
++error;
goto bail;
/* LCOV_EXCL_STOP */
}
}
@ -162,8 +164,10 @@ static void state_hash_process(struct snapraid_state* state, block_off_t blockst
printf("Stopping to allow recovery. Try with 'snapraid check -f %s'\n", file->sub);
}
/* LCOV_EXCL_START */
++error;
goto bail;
/* LCOV_EXCL_STOP */
}
/* check if the file is changed */
@ -193,12 +197,14 @@ static void state_hash_process(struct snapraid_state* state, block_off_t blockst
read_size = handle_read(&handle[j], block, buffer, state->block_size, stderr);
if (read_size == -1) {
/* LCOV_EXCL_START */
fprintf(stdlog, "error:%u:%s:%s: Read error at position %u\n", i, handle[j].disk->name, handle[j].file->sub, block_file_pos(block));
fprintf(stderr, "DANGER! Unexpected read error in a data disk, it isn't possible to sync.\n");
fprintf(stderr, "Ensure that disk '%s' is sane and that file '%s' can be read.\n", handle[j].disk->dir, handle[j].path);
printf("Stopping to allow recovery. Try with 'snapraid check -f %s'\n", handle[j].file->sub);
++error;
goto bail;
/* LCOV_EXCL_STOP */
}
countsize += read_size;
@ -224,7 +230,9 @@ static void state_hash_process(struct snapraid_state* state, block_off_t blockst
/* progress */
if (state_progress(state, i, countpos, countmax, countsize)) {
/* LCOV_EXCL_START */
break;
/* LCOV_EXCL_STOP */
}
}
@ -235,6 +243,7 @@ static void state_hash_process(struct snapraid_state* state, block_off_t blockst
ret = handle_close(&handle[j]);
if (ret == -1) {
/* LCOV_EXCL_START */
/* This one is really an unexpected error, because we are only reading */
/* and closing a descriptor should never fail */
fprintf(stdlog, "error:%u:%s:%s: Close error. %s\n", blockmax, handle[j].disk->name, file->sub, strerror(errno));
@ -243,6 +252,7 @@ static void state_hash_process(struct snapraid_state* state, block_off_t blockst
printf("Stopping at block %u\n", blockmax);
++error;
goto bail;
/* LCOV_EXCL_STOP */
}
}
}
@ -516,6 +526,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
struct snapraid_file* file = handle[j].file;
ret = handle_close(&handle[j]);
if (ret == -1) {
/* LCOV_EXCL_START */
/* This one is really an unexpected error, because we are only reading */
/* and closing a descriptor should never fail */
fprintf(stdlog, "error:%u:%s:%s: Close error. %s\n", i, handle[j].disk->name, file->sub, strerror(errno));
@ -524,6 +535,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
printf("Stopping at block %u\n", i);
++error;
goto bail;
/* LCOV_EXCL_STOP */
}
}
@ -561,8 +573,10 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
printf("Stopping to allow recovery. Try with 'snapraid check -f %s'\n", file->sub);
}
/* LCOV_EXCL_START */
++error;
goto bail;
/* LCOV_EXCL_STOP */
}
/* check if the file is changed */
@ -593,12 +607,14 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
read_size = handle_read(&handle[j], block, buffer[j], state->block_size, stderr);
if (read_size == -1) {
/* LCOV_EXCL_START */
fprintf(stdlog, "error:%u:%s:%s: Read error at position %u\n", i, handle[j].disk->name, handle[j].file->sub, block_file_pos(block));
fprintf(stderr, "DANGER! Unexpected read error in a data disk, it isn't possible to sync.\n");
fprintf(stderr, "Ensure that disk '%s' is sane and that file '%s' can be read.\n", handle[j].disk->dir, handle[j].path);
printf("Stopping to allow recovery. Try with 'snapraid check -f %s'\n", handle[j].file->sub);
++error;
goto bail;
/* LCOV_EXCL_STOP */
}
countsize += read_size;
@ -723,12 +739,14 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
for(l=0;l<state->level;++l) {
ret = parity_read(parity[l], i, buffer[diskmax+l], state->block_size, stdlog);
if (ret == -1) {
/* LCOV_EXCL_START */
fprintf(stdlog, "parity_error:%u:%s: Read error\n", i, lev_config_name(l));
fprintf(stderr, "DANGER! Read error in the %s disk, it isn't possible to sync.\n", lev_name(l));
fprintf(stderr, "Ensure that disk '%s' is sane.\n", lev_config_name(l));
printf("Stopping at block %u\n", i);
++error;
goto bail;
/* LCOV_EXCL_STOP */
}
}
@ -788,12 +806,14 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
for(l=0;l<state->level;++l) {
ret = parity_write(parity[l], i, buffer[diskmax+l], state->block_size);
if (ret == -1) {
/* LCOV_EXCL_START */
fprintf(stdlog, "parity_error:%u:%s: Write error\n", i, lev_config_name(l));
fprintf(stderr, "DANGER! Write error in the %s disk, it isn't possible to sync.\n", lev_name(l));
fprintf(stderr, "Ensure that disk '%s' is sane.\n", lev_config_name(l));
printf("Stopping at block %u\n", i);
++error;
goto bail;
/* LCOV_EXCL_STOP */
}
}
}
@ -859,7 +879,9 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
/* progress */
if (state_progress(state, i, countpos, countmax, countsize)) {
/* LCOV_EXCL_START */
break;
/* LCOV_EXCL_STOP */
}
/* autosave */
@ -945,8 +967,10 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
loaded_size = state->loaded_paritymax * (data_off_t)state->block_size;
if (blockstart > blockmax) {
/* LCOV_EXCL_START */
fprintf(stderr, "Error in the starting block %u. It's bigger than the parity size %u.\n", blockstart, blockmax);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* adjust the number of block to process */
@ -959,14 +983,18 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
parity_ptr[l] = &parity[l];
ret = parity_create(parity_ptr[l], state->parity_path[l], &out_size, state->opt.skip_sequential);
if (ret == -1) {
/* LCOV_EXCL_START */
fprintf(stderr, "WARNING! Without an accessible %s file, it isn't possible to sync.\n", lev_name(l));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* if the file is too small */
if (out_size < loaded_size) {
/* LCOV_EXCL_START */
fprintf(stderr, "DANGER! The %s file %s is smaller than the expected %" PRId64 ".\n", lev_name(l), state->parity_path[l], loaded_size);
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
/* change the size of the parity file, truncating or extending it */
@ -974,9 +1002,11 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
/* and they are automatically removed when we save the new content file */
ret = parity_chsize(parity_ptr[l], size, &out_size, state->opt.skip_fallocate);
if (ret == -1) {
/* LCOV_EXCL_START */
parity_overflow(state, out_size);
fprintf(stderr, "WARNING! Without an accessible %s file, it isn't possible to sync.\n", lev_name(l));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
}
@ -997,8 +1027,10 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
if (blockstart < blockmax) {
ret = state_sync_process(state, parity_ptr, blockstart, blockmax);
if (ret == -1) {
/* LCOV_EXCL_START */
++unrecoverable_error;
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */
}
} else {
printf("Nothing to do\n");
@ -1007,16 +1039,20 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
for(l=0;l<state->level;++l) {
ret = parity_sync(parity_ptr[l]);
if (ret == -1) {
/* LCOV_EXCL_START */
fprintf(stderr, "DANGER! Unexpected sync error in %s disk.\n", lev_name(l));
++unrecoverable_error;
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */
}
ret = parity_close(parity_ptr[l]);
if (ret == -1) {
/* LCOV_EXCL_START */
fprintf(stderr, "DANGER! Unexpected close error in %s disk.\n", lev_name(l));
++unrecoverable_error;
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */
}
}