mirror of
https://github.com/NixOS/nix
synced 2025-07-07 22:33:57 +02:00
Merge pull request #11763 from NixOS/mergify/bp/2.24-maintenance/pr-11751
Add support for `utimensat` as an alternative to `lutimes` (backport #11751)
This commit is contained in:
commit
baa7565710
3 changed files with 43 additions and 38 deletions
|
@ -89,9 +89,10 @@ AC_LANG_POP(C++)
|
||||||
AC_CHECK_FUNCS([statvfs pipe2])
|
AC_CHECK_FUNCS([statvfs pipe2])
|
||||||
|
|
||||||
|
|
||||||
# Check for lutimes, optionally used for changing the mtime of
|
# Check for lutimes and utimensat, optionally used for changing the
|
||||||
# symlinks.
|
# mtime of symlinks.
|
||||||
AC_CHECK_FUNCS([lutimes])
|
AC_CHECK_DECLS([AT_SYMLINK_NOFOLLOW], [], [], [[#include <fcntl.h>]])
|
||||||
|
AC_CHECK_FUNCS([lutimes utimensat])
|
||||||
|
|
||||||
|
|
||||||
# Check whether the store optimiser can optimise symlinks.
|
# Check whether the store optimiser can optimise symlinks.
|
||||||
|
|
|
@ -574,7 +574,28 @@ void setWriteTime(
|
||||||
time_t modificationTime,
|
time_t modificationTime,
|
||||||
std::optional<bool> optIsSymlink)
|
std::optional<bool> optIsSymlink)
|
||||||
{
|
{
|
||||||
#ifndef _WIN32
|
#ifdef _WIN32
|
||||||
|
// FIXME use `fs::last_write_time`.
|
||||||
|
//
|
||||||
|
// Would be nice to use std::filesystem unconditionally, but
|
||||||
|
// doesn't support access time just modification time.
|
||||||
|
//
|
||||||
|
// System clock vs File clock issues also make that annoying.
|
||||||
|
warn("Changing file times is not yet implemented on Windows, path is '%s'", path);
|
||||||
|
#elif HAVE_UTIMENSAT && HAVE_DECL_AT_SYMLINK_NOFOLLOW
|
||||||
|
struct timespec times[2] = {
|
||||||
|
{
|
||||||
|
.tv_sec = accessedTime,
|
||||||
|
.tv_nsec = 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.tv_sec = modificationTime,
|
||||||
|
.tv_nsec = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if (utimensat(AT_FDCWD, path.c_str(), times, AT_SYMLINK_NOFOLLOW) == -1)
|
||||||
|
throw SysError("changing modification time of '%s' (using `utimensat`)", path);
|
||||||
|
#else
|
||||||
struct timeval times[2] = {
|
struct timeval times[2] = {
|
||||||
{
|
{
|
||||||
.tv_sec = accessedTime,
|
.tv_sec = accessedTime,
|
||||||
|
@ -585,42 +606,21 @@ void setWriteTime(
|
||||||
.tv_usec = 0,
|
.tv_usec = 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
#endif
|
#if HAVE_LUTIMES
|
||||||
|
if (lutimes(path.c_str(), times) == -1)
|
||||||
auto nonSymlink = [&]{
|
throw SysError("changing modification time of '%s'", path);
|
||||||
|
#else
|
||||||
bool isSymlink = optIsSymlink
|
bool isSymlink = optIsSymlink
|
||||||
? *optIsSymlink
|
? *optIsSymlink
|
||||||
: fs::is_symlink(path);
|
: fs::is_symlink(path);
|
||||||
|
|
||||||
if (!isSymlink) {
|
if (!isSymlink) {
|
||||||
#ifdef _WIN32
|
if (utimes(path.c_str(), times) == -1)
|
||||||
// FIXME use `fs::last_write_time`.
|
|
||||||
//
|
|
||||||
// Would be nice to use std::filesystem unconditionally, but
|
|
||||||
// doesn't support access time just modification time.
|
|
||||||
//
|
|
||||||
// System clock vs File clock issues also make that annoying.
|
|
||||||
warn("Changing file times is not yet implemented on Windows, path is '%s'", path);
|
|
||||||
#else
|
|
||||||
if (utimes(path.c_str(), times) == -1) {
|
|
||||||
|
|
||||||
throw SysError("changing modification time of '%s' (not a symlink)", path);
|
throw SysError("changing modification time of '%s' (not a symlink)", path);
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
throw Error("Cannot modification time of symlink '%s'", path);
|
throw Error("Cannot modification time of symlink '%s'", path);
|
||||||
}
|
}
|
||||||
};
|
#endif
|
||||||
|
|
||||||
#if HAVE_LUTIMES
|
|
||||||
if (lutimes(path.c_str(), times) == -1) {
|
|
||||||
if (errno == ENOSYS)
|
|
||||||
nonSymlink();
|
|
||||||
else
|
|
||||||
throw SysError("changing modification time of '%s'", path);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
nonSymlink();
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,8 @@ check_funcs = [
|
||||||
# Optionally used to try to close more file descriptors (e.g. before
|
# Optionally used to try to close more file descriptors (e.g. before
|
||||||
# forking) on Unix.
|
# forking) on Unix.
|
||||||
'sysconf',
|
'sysconf',
|
||||||
|
# Optionally used for changing the mtime of files and symlinks.
|
||||||
|
'utimensat',
|
||||||
]
|
]
|
||||||
foreach funcspec : check_funcs
|
foreach funcspec : check_funcs
|
||||||
define_name = 'HAVE_' + funcspec.underscorify().to_upper()
|
define_name = 'HAVE_' + funcspec.underscorify().to_upper()
|
||||||
|
@ -48,6 +50,8 @@ foreach funcspec : check_funcs
|
||||||
configdata.set(define_name, define_value)
|
configdata.set(define_name, define_value)
|
||||||
endforeach
|
endforeach
|
||||||
|
|
||||||
|
configdata.set('HAVE_DECL_AT_SYMLINK_NOFOLLOW', cxx.has_header_symbol('fcntl.h', 'AT_SYMLINK_NOFOLLOW').to_int())
|
||||||
|
|
||||||
subdir('build-utils-meson/threads')
|
subdir('build-utils-meson/threads')
|
||||||
|
|
||||||
if host_machine.system() == 'windows'
|
if host_machine.system() == 'windows'
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue