mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
Set time of pool links
This avoid index refresh from various applications.
This commit is contained in:
parent
71c11d7ecd
commit
17bec43be2
8 changed files with 141 additions and 7 deletions
1
HISTORY
1
HISTORY
|
|
@ -13,6 +13,7 @@ SnapRAID HISTORY
|
|||
compatibility.
|
||||
* Fixed building in platforms that don't provide major/minor definitions
|
||||
in sys/types.h.
|
||||
* When creating 'pool' symbolic links, set their time as the linked files.
|
||||
* Added support for the Windows 10 symbolic link unprivileged creation,
|
||||
using SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE.
|
||||
* Windows binaries built with gcc 4.9.4 using the MXE cross compiler at
|
||||
|
|
|
|||
3
TODO
3
TODO
|
|
@ -5,9 +5,6 @@ This is the list of TODO items for SnapRAID.
|
|||
|
||||
- Next
|
||||
|
||||
* When creating links, set the mtime like the linked file.
|
||||
See: https://sourceforge.net/p/snapraid/discussion/1677233/thread/936f0087/?limit=25#b3d6
|
||||
|
||||
- Minor
|
||||
|
||||
* Allow to filter in diff/list by disk name.
|
||||
|
|
|
|||
|
|
@ -1040,6 +1040,70 @@ int windows_futimens(int fd, struct windows_timespec tv[2])
|
|||
return 0;
|
||||
}
|
||||
|
||||
int windows_utimensat(int fd, const char* file, struct windows_timespec tv[2], int flags)
|
||||
{
|
||||
wchar_t conv_buf[CONV_MAX];
|
||||
HANDLE h;
|
||||
FILETIME ft;
|
||||
uint64_t mtime;
|
||||
DWORD wflags;
|
||||
|
||||
/*
|
||||
* Support only the absolute paths
|
||||
*/
|
||||
if (fd != AT_FDCWD) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the handle of the file.
|
||||
*
|
||||
* Use FILE_FLAG_BACKUP_SEMANTICS to open directories (it's just ignored for files).
|
||||
* Use FILE_FLAG_OPEN_REPARSE_POINT to open symbolic links and not the their target.
|
||||
*
|
||||
* Note that even with FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
* and FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT some paths
|
||||
* cannot be opened like "C:\System Volume Information" resulting
|
||||
* in error ERROR_ACCESS_DENIED.
|
||||
*/
|
||||
wflags = FILE_FLAG_BACKUP_SEMANTICS;
|
||||
if ((flags & AT_SYMLINK_NOFOLLOW) != 0)
|
||||
wflags |= FILE_FLAG_OPEN_REPARSE_POINT;
|
||||
h = CreateFileW(convert(conv_buf, file), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, wflags, 0);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
windows_errno(GetLastError());
|
||||
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_nsec / 100;
|
||||
mtime += 116444736000000000;
|
||||
|
||||
ft.dwHighDateTime = mtime >> 32;
|
||||
ft.dwLowDateTime = mtime;
|
||||
|
||||
if (!SetFileTime(h, 0, 0, &ft)) {
|
||||
windows_errno(GetLastError());
|
||||
CloseHandle(h);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!CloseHandle(h)) {
|
||||
windows_errno(GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int windows_rename(const char* from, const char* to)
|
||||
{
|
||||
wchar_t conv_buf_from[CONV_MAX];
|
||||
|
|
|
|||
|
|
@ -85,6 +85,11 @@
|
|||
#define HAVE_FUTIMENS 1
|
||||
#undef futimens
|
||||
#define futimens windows_futimens
|
||||
#define HAVE_UTIMENSAT 1
|
||||
#define AT_FDCWD -1
|
||||
#define AT_SYMLINK_NOFOLLOW 1
|
||||
#undef utimensat
|
||||
#define utimensat windows_utimensat
|
||||
#define O_NOFOLLOW 0
|
||||
#define dirent_hidden windows_dirent_hidden
|
||||
#define HAVE_STRUCT_DIRENT_D_STAT 1
|
||||
|
|
@ -241,6 +246,11 @@ struct windows_timespec {
|
|||
*/
|
||||
int windows_futimens(int fd, struct windows_timespec tv[2]);
|
||||
|
||||
/**
|
||||
* Like the C utimensat().
|
||||
*/
|
||||
int windows_utimensat(int fd, const char* file, struct windows_timespec tv[2], int flags);
|
||||
|
||||
/**
|
||||
* Like the C rename().
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ static int clean_dir(struct snapraid_state* state, const char* dir)
|
|||
/**
|
||||
* Create a link to the specified disk entry.
|
||||
*/
|
||||
static void make_link(const char* pool_dir, const char* share_dir, struct snapraid_disk* disk, const char* sub)
|
||||
static void make_link(const char* pool_dir, const char* share_dir, struct snapraid_disk* disk, const char* sub, int64_t mtime_sec, int mtime_nsec)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
char linkto[PATH_MAX];
|
||||
|
|
@ -196,6 +196,16 @@ static void make_link(const char* pool_dir, const char* share_dir, struct snapra
|
|||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
}
|
||||
|
||||
if (mtime_sec) {
|
||||
ret = lmtime(path, mtime_sec, mtime_nsec);
|
||||
if (ret != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal("Error setting time to symlink '%s'. %s.\n", path, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void state_pool(struct snapraid_state* state)
|
||||
|
|
@ -236,14 +246,14 @@ void state_pool(struct snapraid_state* state)
|
|||
/* for each file */
|
||||
for (j = disk->filelist; j != 0; j = j->next) {
|
||||
struct snapraid_file* file = j->data;
|
||||
make_link(pool_dir, share_dir, disk, file->sub);
|
||||
make_link(pool_dir, share_dir, disk, file->sub, file->mtime_sec, file->mtime_nsec);
|
||||
++count;
|
||||
}
|
||||
|
||||
/* for each link */
|
||||
for (j = disk->linklist; j != 0; j = j->next) {
|
||||
struct snapraid_link* slink = j->data;
|
||||
make_link(pool_dir, share_dir, disk, slink->sub);
|
||||
make_link(pool_dir, share_dir, disk, slink->sub, 0, 0);
|
||||
++count;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -897,6 +897,52 @@ int fmtime(int f, int64_t mtime_sec, int mtime_nsec)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int lmtime(const char* path, int64_t mtime_sec, int mtime_nsec)
|
||||
{
|
||||
#if HAVE_UTIMENSAT
|
||||
struct timespec tv[2];
|
||||
#else
|
||||
struct timeval tv[2];
|
||||
#endif
|
||||
int ret;
|
||||
|
||||
#if HAVE_UTIMENSAT /* utimensat() 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 = utimensat(AT_FDCWD, path, tv, AT_SYMLINK_NOFOLLOW);
|
||||
#elif HAVE_LUTIMES /* fallback to lutimes() 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 = lutimes(path, 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(AT_FDCWD, path, tv);
|
||||
#else
|
||||
#error No function available to set file timestamps with sub-second precision
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* advise */
|
||||
|
||||
|
|
|
|||
|
|
@ -322,6 +322,12 @@ int mkancestor(const char* file);
|
|||
*/
|
||||
int fmtime(int f, int64_t mtime_sec, int mtime_nsec);
|
||||
|
||||
/**
|
||||
* Change the modification time of a file or link.
|
||||
* Note that links are NOT deferenced.
|
||||
*/
|
||||
int lmtime(const char* path, int64_t mtime_sec, int mtime_nsec);
|
||||
|
||||
/****************************************************************************/
|
||||
/* advise */
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ AC_CHECK_FUNCS([getopt getopt_long snprintf vsnprintf sigaction])
|
|||
AC_CHECK_FUNCS([ftruncate fallocate access])
|
||||
AC_CHECK_FUNCS([fsync posix_fadvise sync_file_range])
|
||||
AC_CHECK_FUNCS([getc_unlocked ferror_unlocked fnmatch])
|
||||
AC_CHECK_FUNCS([futimes futimens futimesat localtime_r])
|
||||
AC_CHECK_FUNCS([futimes futimens futimesat localtime_r lutimes utimensat])
|
||||
AC_CHECK_FUNCS([fstatat flock statfs])
|
||||
AC_CHECK_FUNCS([mach_absolute_time])
|
||||
AC_CHECK_FUNCS([backtrace backtrace_symbols])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue