mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
Adds the implementation of the new test-nano command.
This commit is contained in:
parent
de86307a27
commit
adc4f196fa
6 changed files with 185 additions and 57 deletions
|
|
@ -1343,11 +1343,12 @@ close_and_continue:
|
|||
}
|
||||
|
||||
/* set the original modification time */
|
||||
ret = file_utime(file, f);
|
||||
ret = fmtime(f, file->mtime_sec, file->mtime_nsec);
|
||||
if (ret != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
close(f);
|
||||
|
||||
fprintf(stderr, "Error timing file '%s'. %s.\n", file->sub, 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;
|
||||
|
|
|
|||
|
|
@ -353,52 +353,19 @@ int handle_write(struct snapraid_handle* handle, struct snapraid_block* block, u
|
|||
return 0;
|
||||
}
|
||||
|
||||
int file_utime(struct snapraid_file* file, int f)
|
||||
int handle_utime(struct snapraid_handle* handle)
|
||||
{
|
||||
#if HAVE_FUTIMENS
|
||||
struct timespec tv[2];
|
||||
#else
|
||||
struct timeval tv[2];
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
#if HAVE_FUTIMENS /* futimens() is preferred because it gives nanosecond precision */
|
||||
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;
|
||||
/* do nothing if not opened */
|
||||
if (handle->f == -1)
|
||||
return 0;
|
||||
|
||||
ret = futimens(f, tv);
|
||||
#elif HAVE_FUTIMES /* fallback to futimes() if nanosecond precision is not available */
|
||||
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(f, tv);
|
||||
#elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */
|
||||
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(f, 0, tv);
|
||||
#else
|
||||
#error No function available to set file timestamps with sub-second precision
|
||||
#endif
|
||||
ret = fmtime(handle->f, handle->file->mtime_sec, handle->file->mtime_nsec);
|
||||
|
||||
if (ret != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
fprintf(stderr, "Error timing file '%s'. %s.\n", file->sub, strerror(errno));
|
||||
fprintf(stderr, "Error timing file '%s'. %s.\n", handle->file->sub, strerror(errno));
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
|
@ -406,15 +373,6 @@ int file_utime(struct snapraid_file* file, int f)
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -20,14 +20,6 @@
|
|||
|
||||
#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 */
|
||||
|
||||
|
|
|
|||
120
cmdline/nano.c
Normal file
120
cmdline/nano.c
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Andrea Mazzoleni
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "elem.h"
|
||||
#include "state.h"
|
||||
#include "handle.h"
|
||||
|
||||
void state_nano(struct snapraid_state* state)
|
||||
{
|
||||
tommy_node* i;
|
||||
|
||||
printf("Setting nanosecond timestamps...\n");
|
||||
|
||||
/* for all disks */
|
||||
for(i=state->disklist;i!=0;i=i->next) {
|
||||
struct snapraid_disk* disk = i->data;
|
||||
tommy_node* j;
|
||||
|
||||
/* for all files */
|
||||
for(j=disk->filelist;j!=0;j=j->next) {
|
||||
struct snapraid_file* file = j->data;
|
||||
|
||||
/* if the file has a zero nanosecond timestamp */
|
||||
if (file->mtime_nsec == 0) {
|
||||
char path[PATH_MAX];
|
||||
struct stat st;
|
||||
int f;
|
||||
int ret;
|
||||
int nsec;
|
||||
|
||||
pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub);
|
||||
|
||||
/* generate a new nanosecond timestamp different than 0 */
|
||||
do {
|
||||
nsec = rand() % 1000000000;
|
||||
} while (nsec == 0);
|
||||
|
||||
/* uses stat to get the present timestamp */
|
||||
ret = stat(path, &st);
|
||||
if (ret == -1) {
|
||||
/* LCOV_EXCL_START */
|
||||
fprintf(stderr, "Error accessing file '%s'. %s.\n", path, strerror(errno));
|
||||
continue;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* open it */
|
||||
/* O_NOFOLLOW: do not follow links to ensure to open the real file */
|
||||
f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW);
|
||||
if (f == -1) {
|
||||
/* LCOV_EXCL_START */
|
||||
fprintf(stderr, "Error opening file '%s'. %s.\n", path, strerror(errno));
|
||||
continue;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* set the tweaked modification time */
|
||||
ret = fmtime(f, st.st_mtime, nsec);
|
||||
if (ret != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
close(f);
|
||||
|
||||
fprintf(stderr, "Error timing file '%s'. %s.\n", path, strerror(errno));
|
||||
continue;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* close it */
|
||||
ret = close(f);
|
||||
if (ret != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
fprintf(stderr, "Error closing file '%s'. %s.\n", path, strerror(errno));
|
||||
continue;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* uses stat again to get the present timestamp */
|
||||
/* this is needed because the value read */
|
||||
/* may be different than the written one */
|
||||
ret = stat(path, &st);
|
||||
if (ret == -1) {
|
||||
/* LCOV_EXCL_START */
|
||||
fprintf(stderr, "Error accessing file '%s'. %s.\n", path, strerror(errno));
|
||||
continue;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* set the same nanosecond value in the content file */
|
||||
/* note that if the second value is already matching */
|
||||
/* the file won't be synched because the content file will */
|
||||
/* contain the new updated timestamp */
|
||||
file->mtime_nsec = STAT_NSEC(&st);
|
||||
|
||||
/* state changed, we need to update it */
|
||||
state->need_write = 1;
|
||||
|
||||
fprintf(stdlog, "nano:%s:%s\n", disk->name, file->sub);
|
||||
printf("nano %s%s\n", disk->dir, file->sub);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1690,3 +1690,52 @@ int lock_unlock(int f)
|
|||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
/* file */
|
||||
|
||||
int fmtime(int f, int64_t mtime_sec, int mtime_nsec)
|
||||
{
|
||||
#if HAVE_FUTIMENS
|
||||
struct timespec tv[2];
|
||||
#else
|
||||
struct timeval tv[2];
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
#if HAVE_FUTIMENS /* futimens() is preferred because it gives nanosecond precision */
|
||||
tv[0].tv_sec = mtime_sec;
|
||||
if (mtime_nsec != STAT_NSEC_INVALID)
|
||||
tv[0].tv_nsec = 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(f, tv);
|
||||
#elif HAVE_FUTIMES /* fallback to futimes() if nanosecond precision is not available */
|
||||
tv[0].tv_sec = mtime_sec;
|
||||
if (mtime_nsec != STAT_NSEC_INVALID)
|
||||
tv[0].tv_usec = 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(f, tv);
|
||||
#elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */
|
||||
tv[0].tv_sec = mtime_sec;
|
||||
if (mtime_nsec != STAT_NSEC_INVALID)
|
||||
tv[0].tv_usec = 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(f, 0, tv);
|
||||
#else
|
||||
#error No function available to set file timestamps with sub-second precision
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -558,5 +558,13 @@ int lock_lock(const char* file);
|
|||
*/
|
||||
int lock_unlock(int f);
|
||||
|
||||
/****************************************************************************/
|
||||
/* file */
|
||||
|
||||
/**
|
||||
* Changes the modification time of an open file.
|
||||
*/
|
||||
int fmtime(int f, int64_t mtime_sec, int mtime_nsec);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue