Compiles with optional nanoseconds supports.

This commit is contained in:
Andrea Mazzoleni 2012-09-19 21:52:15 +02:00
parent 7d6251c698
commit 3c598b28cc
8 changed files with 63 additions and 61 deletions

View file

@ -38,12 +38,13 @@ AC_TYPE_UINT32_T
AC_TYPE_UINT64_T
AC_TYPE_UINT8_T
AC_TYPE_INT8_T
AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec, struct stat.st_mtimensec, struct stat.st_mtimespec.tv_nsec], [], [], [[#include <sys/stat.h>]])
dnl Checks for library functions.
AC_SYS_LARGEFILE
AC_CHECK_FUNCS([memset strchr strerror strrchr mkdir gettimeofday strtoul])
AC_CHECK_FUNCS([getopt getopt_long snprintf vsnprintf])
AC_CHECK_FUNCS([ftruncate fallocate fsync access posix_fallocate posix_fadvise pread pwrite getc_unlocked ferror_unlocked fnmatch])
AC_CHECK_FUNCS([ftruncate fallocate fsync access posix_fallocate posix_fadvise pread pwrite getc_unlocked ferror_unlocked fnmatch futimes futimens])
dnl Checks for architecture
AC_C_BIGENDIAN

View file

@ -327,20 +327,39 @@ int handle_write(struct snapraid_handle* handle, struct snapraid_block* block, u
int handle_utime(struct snapraid_handle* handle)
{
#if HAVE_FUTIMENS
struct timespec tv[2];
#else
struct timeval tv[2];
#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;
tv[0].tv_nsec = handle->file->mtime_nsec;
if (handle->file->mtime_nsec != FILE_MTIME_NSEC_INVALID)
tv[0].tv_nsec = handle->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);
#else
tv[0].tv_sec = handle->file->mtime_sec;
if (handle->file->mtime_nsec != FILE_MTIME_NSEC_INVALID)
tv[0].tv_usec = handle->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);
#endif
if (ret != 0) {
fprintf(stderr, "Error timing file '%s'. %s.\n", handle->file->sub, strerror(errno));
return -1;

43
mingw.c
View file

@ -203,7 +203,7 @@ static void windows_info2stat(const BY_HANDLE_FILE_INFORMATION* info, struct win
*/
mtime -= 116444736000000000LL;
st->st_mtime = mtime / 10000000;
st->st_mtim.tv_nsec = (mtime % 10000000) * 100;
st->st_mtimensec = (mtime % 10000000) * 100;
st->st_ino = info->nFileIndexHigh;
st->st_ino <<= 32;
@ -264,7 +264,7 @@ static void windows_finddata2stat(const WIN32_FIND_DATAW* info, struct windows_s
*/
mtime -= 116444736000000000LL;
st->st_mtime = mtime / 10000000;
st->st_mtim.tv_nsec = (mtime % 10000000) * 100;
st->st_mtimensec = (mtime % 10000000) * 100;
/* No inode information available */
st->st_ino = 0;
@ -470,45 +470,6 @@ int windows_ftruncate(int fd, off64_t off)
return 0;
}
int windows_futimes(int fd, struct timeval tv[2])
{
HANDLE h;
FILETIME ft;
uint64_t mtime;
if (fd == -1) {
errno = EBADF;
return -1;
}
h = (HANDLE)_get_osfhandle(fd);
if (h == INVALID_HANDLE_VALUE) {
errno = EBADF;
return -1;
}
/*
* Convert to windows time
*
* How To Convert a UNIX time_t to a Win32 FILETIME or SYSTEMTIME
* http://support.microsoft.com/kb/167296
*/
mtime = tv[0].tv_sec;
mtime *= 10000000;
mtime += tv[0].tv_usec * 10;
mtime += 116444736000000000;
ft.dwHighDateTime = mtime >> 32;
ft.dwLowDateTime = mtime;
if (!SetFileTime(h, 0, 0, &ft)) {
windows_errno(GetLastError());
return -1;
}
return 0;
}
int windows_futimens(int fd, struct windows_timespec tv[2])
{
HANDLE h;

View file

@ -49,7 +49,7 @@
#define opendir windows_opendir
#define readdir windows_readdir
#define closedir windows_closedir
#define futimes windows_futimes
#define HAVE_FUTIMENS 1
#define futimens windows_futimens
#define O_NOFOLLOW 0
#define stat_hidden windows_stat_hidden
@ -60,10 +60,6 @@
#define readlink(a,b,c) -1
#define symlink(a,b) -1
struct windows_mtim {
int tv_nsec;
};
/**
* Generic stat information.
*/
@ -71,7 +67,7 @@ struct windows_stat {
uint64_t st_ino;
int64_t st_size;
int64_t st_mtime;
struct windows_mtim st_mtim;
int32_t st_mtimensec;
uint32_t st_mode;
uint32_t st_nlink;
uint32_t st_dev;

View file

@ -112,10 +112,31 @@
#ifdef __MINGW32__ /* Specific for MingW */
#include "mingw.h"
/* We have nano second support */
#define STAT_NSEC(st) (st)->st_mtimensec
#else /* Specific for Unix */
#define O_BINARY 0 /**< Not used in Unix. */
#define O_SEQUENTIAL 0 /**< In Unix posix_fadvise() shall be used. */
/* Check if we have nanoseconds support */
#if HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
#define STAT_NSEC(st) (st)->st_mtim.tv_nsec /* Linux */
#elif HAVE_STRUCT_STAT_ST_MTIMENSEC
#define STAT_NSEC(st) (st)->st_mtimensec /* FreeBSD, Mac OS X if _POSIX_C_SOURCE defined */
#elif HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
#define STAT_NSEC(st) (st)->st_mtimespec.tv_nsec /* Mac OS X if _POSIX_C_SOURCE not defined */
#else
/**
* If nanoseconds are not supported, we report the special FILE_MTIME_NSEC_INVALID value,
* to mark that it's undefined.
* This result in not having it saved into the content file as a dummy 0.
*/
#define STAT_NSEC(st) -1
#endif
/**
* Check if the specified file is hidden.
*/

10
scan.c
View file

@ -174,14 +174,16 @@ static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state,
&& file->mtime_sec == st->st_mtime
/* always accept the value if it's FILE_MTIME_NSEC_INVALID */
/* it happens when upgrading from an old version of SnapRAID */
&& (file->mtime_nsec == st->st_mtim.tv_nsec || file->mtime_nsec == FILE_MTIME_NSEC_INVALID)
&& (file->mtime_nsec == STAT_NSEC(st) || file->mtime_nsec == FILE_MTIME_NSEC_INVALID)
) {
/* mark as present */
file_flag_set(file, FILE_IS_PRESENT);
/* update the nano seconds mtime if required */
if (file->mtime_nsec == FILE_MTIME_NSEC_INVALID) {
file->mtime_nsec = st->st_mtim.tv_nsec;
if (file->mtime_nsec == FILE_MTIME_NSEC_INVALID
&& STAT_NSEC(st) != FILE_MTIME_NSEC_INVALID
) {
file->mtime_nsec = STAT_NSEC(st);
/* we have to save the new mtime */
state->need_write = 1;
@ -315,7 +317,7 @@ static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state,
}
/* insert it */
file = file_alloc(state->block_size, sub, st->st_size, st->st_mtime, st->st_mtim.tv_nsec, st->st_ino);
file = file_alloc(state->block_size, sub, st->st_size, st->st_mtime, STAT_NSEC(st), st->st_ino);
/* mark it as present */
file_flag_set(file, FILE_IS_PRESENT);

12
state.c
View file

@ -900,7 +900,7 @@ void state_read(struct snapraid_state* state)
/* use a special value, meaning that we don't have this information */
v_mtime_nsec = FILE_MTIME_NSEC_INVALID;
}
if (c != ' ') {
fprintf(stderr, "Invalid 'file' specification in '%s' at line %u\n", path, line);
exit(EXIT_FAILURE);
@ -1303,7 +1303,7 @@ void state_write(struct snapraid_state* state)
block_off_t k;
uint64_t size;
uint64_t mtime_sec;
uint32_t mtime_nsec;
int32_t mtime_nsec;
uint64_t inode;
size = file->size;
@ -1321,9 +1321,11 @@ void state_write(struct snapraid_state* state)
sputc(' ', f);
sputu64(mtime_sec, f);
hash = oathash64(hash, mtime_sec);
sputc('.', f);
sputu32(mtime_nsec, f);
hash = oathash32(hash, mtime_nsec);
if (mtime_nsec != FILE_MTIME_NSEC_INVALID) {
sputc('.', f);
sputu32(mtime_nsec, f);
hash = oathash32(hash, mtime_nsec);
}
sputc(' ', f);
sputu64(inode, f);
hash = oathash64(hash, inode);

4
sync.c
View file

@ -204,13 +204,13 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
/* check if the file is changed */
if (handle[j].st.st_size != block_file_get(block)->size
|| handle[j].st.st_mtime != block_file_get(block)->mtime_sec
|| handle[j].st.st_mtim.tv_nsec != block_file_get(block)->mtime_nsec
|| STAT_NSEC(&handle[j].st) != block_file_get(block)->mtime_nsec
|| handle[j].st.st_ino != block_file_get(block)->inode
) {
if (handle[j].st.st_size != block_file_get(block)->size)
fprintf(stderr, "Unexpected size change at file '%s'.\n", handle[j].path);
else if (handle[j].st.st_mtime != block_file_get(block)->mtime_sec
|| handle[j].st.st_mtim.tv_nsec != block_file_get(block)->mtime_nsec)
|| STAT_NSEC(&handle[j].st) != block_file_get(block)->mtime_nsec)
fprintf(stderr, "Unexpected time change at file '%s'.\n", handle[j].path);
else
fprintf(stderr, "Unexpected inode change from %"PRIu64" to %"PRIu64" at file '%s'.\n", block_file_get(block)->inode, handle[j].st.st_ino, handle[j].path);