Restores the timestamp of empty files in fix.

This commit is contained in:
Andrea Mazzoleni 2013-08-26 20:20:36 +02:00
parent 1e5a9b5992
commit 3a5ce4e522
3 changed files with 52 additions and 22 deletions

25
check.c
View file

@ -1034,7 +1034,7 @@ static int state_check_process(struct snapraid_state* state, int check, int fix,
collide_file = tommy_hashdyn_search(&handle[j].disk->inodeset, file_inode_compare_to_arg, &inode, file_inode_hash(inode));
/* if the inode is already in the database and it refers at a different file name, */
/* we can fix the file time ONLY if the time and size allow to differentiates */
/* we can fix the file time ONLY if the time and size allow to differentiate */
/* between the two files */
/* for example, suppose we delete a bunch of files with all the same size and time, */
@ -1045,7 +1045,7 @@ static int state_check_process(struct snapraid_state* state, int check, int fix,
|| 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
|| collide_file->mtime_nsec != file->mtime_nsec /* same for mtime_nsec */
) {
/* set the original modification time */
ret = handle_utime(&handle[j]);
@ -1121,7 +1121,7 @@ close_and_continue:
if (!handle[i].disk)
continue;
/* for each file in the disk */
/* for each empty file in the disk */
disk = handle[i].disk;
node = disk->filelist;
while (node) {
@ -1192,8 +1192,25 @@ close_and_continue:
goto bail;
}
/* set the original modification time */
ret = file_utime(file, f);
if (ret != 0) {
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;
}
/* close it */
close(f);
ret = close(f);
if (ret != 0) {
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;
}
fprintf(stdlog, "fixed:%s:%s: Fixed empty file\n", disk->name, file->sub);
++recovered_error;

View file

@ -318,7 +318,7 @@ int handle_write(struct snapraid_handle* handle, struct snapraid_block* block, u
return 0;
}
int handle_utime(struct snapraid_handle* handle)
int file_utime(struct snapraid_file* file, int f)
{
#if HAVE_FUTIMENS
struct timespec tv[2];
@ -327,52 +327,57 @@ int handle_utime(struct snapraid_handle* handle)
#endif
int ret;
/* do nothing if not opened */
if (handle->f == -1)
return 0;
#if HAVE_FUTIMENS /* futimens() is preferred because it gives nanosecond precision */
tv[0].tv_sec = handle->file->mtime_sec;
if (handle->file->mtime_nsec != STAT_NSEC_INVALID)
tv[0].tv_nsec = handle->file->mtime_nsec;
tv[0].tv_sec = file->mtime_sec;
if (file->mtime_nsec != STAT_NSEC_INVALID)
tv[0].tv_nsec = file->mtime_nsec;
else
tv[0].tv_nsec = 0;
tv[1].tv_sec = tv[0].tv_sec;
tv[1].tv_nsec = tv[0].tv_nsec;
ret = futimens(handle->f, tv);
ret = futimens(f, tv);
#elif HAVE_FUTIMES /* fallback to futimes() if nanosecond precision is not available */
tv[0].tv_sec = handle->file->mtime_sec;
if (handle->file->mtime_nsec != STAT_NSEC_INVALID)
tv[0].tv_usec = handle->file->mtime_nsec / 1000;
tv[0].tv_sec = file->mtime_sec;
if (file->mtime_nsec != STAT_NSEC_INVALID)
tv[0].tv_usec = file->mtime_nsec / 1000;
else
tv[0].tv_usec = 0;
tv[1].tv_sec = tv[0].tv_sec;
tv[1].tv_usec = tv[0].tv_usec;
ret = futimes(handle->f, tv);
ret = futimes(f, tv);
#elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */
tv[0].tv_sec = handle->file->mtime_sec;
if (handle->file->mtime_nsec != STAT_NSEC_INVALID)
tv[0].tv_usec = handle->file->mtime_nsec / 1000;
tv[0].tv_sec = file->mtime_sec;
if (file->mtime_nsec != STAT_NSEC_INVALID)
tv[0].tv_usec = file->mtime_nsec / 1000;
else
tv[0].tv_usec = 0;
tv[1].tv_sec = tv[0].tv_sec;
tv[1].tv_usec = tv[0].tv_usec;
ret = futimesat(handle->f, 0, tv);
ret = futimesat(f, 0, tv);
#else
#error No function available to set file timestamps
#endif
if (ret != 0) {
fprintf(stderr, "Error timing file '%s'. %s.\n", handle->file->sub, strerror(errno));
fprintf(stderr, "Error timing file '%s'. %s.\n", file->sub, strerror(errno));
return -1;
}
return 0;
}
int handle_utime(struct snapraid_handle* handle)
{
/* do nothing if not opened */
if (handle->f == -1)
return 0;
return file_utime(handle->file, handle->f);
}
struct snapraid_handle* handle_map(struct snapraid_state* state, unsigned* handlemax)
{
tommy_node* i;

View file

@ -20,6 +20,14 @@
#include "state.h"
/****************************************************************************/
/* file */
/**
* Changes the modification time of a open file to the saved value.
*/
int file_utime(struct snapraid_file* file, int f);
/****************************************************************************/
/* handle */