fs: Refactor UtimesNano replacements

Previously, nodeRestoreTimestamps would do something like

	if node.Type == restic.NodeTypeSymlink {
	    return nodeRestoreSymlinkTimestamps(...)
	}
	return syscall.UtimesNano(...)

where nodeRestoreSymlinkTimestamps was either a no-op or a
reimplementation of syscall.UtimesNano that handles symlinks, with some
repeated converting between timestamp types. The Linux implementation
was a bit clumsy, requiring three syscalls to set the timestamps.

In this new setup, there is a function utimesNano that has three
implementations:

* on Linux, it's a modified syscall.UtimesNano that uses
  AT_SYMLINK_NOFOLLOW and AT_FDCWD so it can handle any type in a single
  call;
* on other Unix platforms, it just calls the syscall function after
  skipping symlinks;
* on Windows, it's the modified UtimesNano that was previously called
  nodeRestoreSymlinkTimestamps, except with different arguments.
This commit is contained in:
greatroar
2024-10-19 12:04:09 +02:00
parent f967a33ccc
commit 8f20d5dcd5
10 changed files with 57 additions and 65 deletions
+4 -4
View File
@@ -42,8 +42,8 @@ func lchown(_ string, _ int, _ int) (err error) {
return nil
}
// restoreSymlinkTimestamps restores timestamps for symlinks
func nodeRestoreSymlinkTimestamps(path string, utimes [2]syscall.Timespec) error {
// utimesNano is like syscall.UtimesNano, except that it sets FILE_FLAG_OPEN_REPARSE_POINT.
func utimesNano(path string, atime, mtime int64, _ restic.NodeType) error {
// tweaked version of UtimesNano from go/src/syscall/syscall_windows.go
pathp, e := syscall.UTF16PtrFromString(fixpath(path))
if e != nil {
@@ -63,8 +63,8 @@ func nodeRestoreSymlinkTimestamps(path string, utimes [2]syscall.Timespec) error
}
}()
a := syscall.NsecToFiletime(syscall.TimespecToNsec(utimes[0]))
w := syscall.NsecToFiletime(syscall.TimespecToNsec(utimes[1]))
a := syscall.NsecToFiletime(atime)
w := syscall.NsecToFiletime(mtime)
return syscall.SetFileTime(h, nil, &a, &w)
}