diff --git a/HISTORY b/HISTORY index b8868d26..6dd833c2 100644 --- a/HISTORY +++ b/HISTORY @@ -17,6 +17,7 @@ SnapRAID HISTORY * Files without read permission generates now an error instead of a warning. You now must explicitely exclude them in the configuration file with exclusion rules. + * In 'check' and 'fix' prints the result for each processed file. 2.1 2013/1 ========== diff --git a/check.c b/check.c index 2176b560..048126a4 100644 --- a/check.c +++ b/check.c @@ -899,82 +899,97 @@ static int state_check_process(struct snapraid_state* state, int check, int fix, } } - /* finish the fix process if it's the last block of the files */ - if (fix) { - /* for all the files of this block check if we need to fix the modification time */ - for(j=0;jdir, file->sub); - /* if it isn't the last block in the file */ - if (!block_is_last(block)) { - /* nothing to do */ - continue; - } + /* if the file is open, it must be the correct block one */ + if (handle[j].file != 0 && handle[j].file != file) { + fprintf(stderr, "Internal inconsistency in opened file for block %u\n", block->parity_pos); + exit(EXIT_FAILURE); + } + /* if the file is excluded, we have nothing to fix */ + /* note that this check is required, because if the file is excluded */ + /* it's also possible to have it not opened, */ + /* and have the handle[j].file pointing to NULL. */ + /* A typical case is if the file is missing, */ + /* and the read-only open failed before. */ + if (file_flag_has(file, FILE_IS_EXCLUDED)) { + /* nothing to do */ + continue; + } + + /* if it isn't the last block in the file */ + if (!block_is_last(block)) { + /* nothing to do */ + continue; + } + + /* finish the fix process if it's the last block of the files */ + if (fix) { /* if the file is damaged, meaning that a fix failed */ - if (file_flag_has(handle[j].file, FILE_IS_DAMAGED)) { + if (file_flag_has(file, FILE_IS_DAMAGED)) { /* rename it to .unrecoverable */ - char path_from[PATH_MAX]; char path_to[PATH_MAX]; - pathprint(path_from, sizeof(path_from), "%s%s", handle[j].disk->dir, handle[j].file->sub); - pathprint(path_to, sizeof(path_to), "%s%s.unrecoverable", handle[j].disk->dir, handle[j].file->sub); + pathprint(path_to, sizeof(path_to), "%s%s.unrecoverable", handle[j].disk->dir, file->sub); /* ensure to operate on a closed file */ ret = handle_close(&handle[j]); if (ret != 0) { - fprintf(stderr, "Error closing '%s'. %s.\n", path_from, strerror(errno)); + 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; } - ret = rename(path_from, path_to); + ret = rename(path, path_to); if (ret != 0) { - fprintf(stderr, "Error renaming '%s' to '%s'. %s.\n", path_from, path_to, strerror(errno)); + 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; } - printf("Unrecoverable '%s'\n", path_from); - fprintf(stdlog, "status:bad:%s:%s\n", handle[j].disk->name, block_file_get(block)->sub); + if (state->gui) { + fprintf(stdlog, "status:unrecoverable:%s:%s\n", handle[j].disk->name, file->sub); + } else { + printf("Unrecoverable '%s'\n", path); + } /* and do not set the time if damaged */ continue; } /* if the file is not fixed, meaning that it is untouched */ - if (!file_flag_has(handle[j].file, FILE_IS_FIXED)) { + if (!file_flag_has(file, FILE_IS_FIXED)) { /* nothing to do */ continue; } - printf("Recovered '%s%s'\n", handle[j].disk->dir, handle[j].file->sub); - fprintf(stdlog, "status:ok:%s:%s\n", handle[j].disk->name, handle[j].file->sub); + if (state->gui) { + fprintf(stdlog, "status:recovered:%s:%s\n", handle[j].disk->name, file->sub); + } else { + printf("Recovered '%s'\n", path); + } inode = handle[j].st.st_ino; @@ -990,16 +1005,16 @@ static int state_check_process(struct snapraid_state* state, int check, int fix, /* and at the next sync some files may have matching inode/size/time even if different name */ /* not allowing sync to detect that the file is changed and not renamed */ if (!collide_file /* if not in the database, there is no collision */ - || strcmp(collide_file->sub, handle[j].file->sub) == 0 /* if the name is the same, it's the right collision */ - || collide_file->size != handle[j].file->size /* if the size is different, the collision is identified */ - || collide_file->mtime_sec != handle[j].file->mtime_sec /* if the mtime is different, the collision is identified */ - || collide_file->mtime_nsec != handle[j].file->mtime_nsec + || strcmp(collide_file->sub, file->sub) == 0 /* if the name is the same, it's the right collision */ + || collide_file->size != file->size /* if the size is different, the collision is identified */ + || collide_file->mtime_sec != file->mtime_sec /* if the mtime is different, the collision is identified */ + || collide_file->mtime_nsec != file->mtime_nsec ) { /* set the original modification time */ ret = handle_utime(&handle[j]); if (ret == -1) { /* mark the file as damaged */ - file_flag_set(handle[j].file, FILE_IS_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; @@ -1008,6 +1023,28 @@ static int state_check_process(struct snapraid_state* state, int check, int fix, } 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); } + } else { + /* we are not fixing, but only checking */ + /* print just the final status */ + if (file_flag_has(file, FILE_IS_DAMAGED)) { + if (state->gui) { + fprintf(stdlog, "status:unrecoverable:%s:%s\n", handle[j].disk->name, file->sub); + } else { + printf("Unrecoverable '%s'\n", path); + } + } else if (file_flag_has(file, FILE_IS_FIXED)) { + if (state->gui) { + fprintf(stdlog, "status:recoverable:%s:%s\n", handle[j].disk->name, file->sub); + } else { + printf("Recoverable '%s'\n", path); + } + } else { + if (state->gui) { + fprintf(stdlog, "status:correct:%s:%s\n", handle[j].disk->name, file->sub); + } else { + printf("Correct '%s'\n", path); + } + } } } @@ -1105,8 +1142,11 @@ static int state_check_process(struct snapraid_state* state, int check, int fix, fprintf(stdlog, "fixed:%s:%s: Fixed empty file\n", disk->name, file->sub); ++recovered_error; - printf("Recovered '%s%s'\n", disk->dir, file->sub); - fprintf(stdlog, "status:ok:%s:%s\n", disk->name, file->sub); + if (state->gui) { + fprintf(stdlog, "status:recovered:%s:%s\n", disk->name, file->sub); + } else { + printf("Recovered '%s%s'\n", disk->dir, file->sub); + } } } @@ -1260,8 +1300,11 @@ static int state_check_process(struct snapraid_state* state, int check, int fix, ++recovered_error; } - printf("Recovered '%s%s'\n", disk->dir, link->sub); - fprintf(stdlog, "status:ok:%s:%s\n", disk->name, link->sub); + if (state->gui) { + fprintf(stdlog, "status:recovered:%s:%s\n", disk->name, link->sub); + } else { + printf("Recovered '%s%s'\n", disk->dir, link->sub); + } } } @@ -1326,8 +1369,11 @@ static int state_check_process(struct snapraid_state* state, int check, int fix, fprintf(stdlog, "dir_fixed:%s:%s: Fixed dir error\n", disk->name, dir->sub); ++recovered_error; - printf("Recovered '%s%s'\n", disk->dir, dir->sub); - fprintf(stdlog, "status:ok:%s:%s\n", disk->name, dir->sub); + if (state->gui) { + fprintf(stdlog, "status:ok:%s:%s\n", disk->name, dir->sub); + } else { + printf("Recovered '%s%s'\n", disk->dir, dir->sub); + } } } } diff --git a/state.h b/state.h index 48b995e9..80126038 100644 --- a/state.h +++ b/state.h @@ -99,7 +99,7 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t /** * Checks (and fixes) all the files and parity data. * \param check If we have to check also the parity. - * \param check If we have to fix, after checking. It requires also check==1. + * \param fix If we have to fix, after checking. It requires also check==1. */ void state_check(struct snapraid_state* state, int check, int fix, block_off_t blockstart, block_off_t blockcount);