aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2021-01-18 15:23:16 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2021-01-25 15:12:58 +0000
commitff82cc971aabd113f3b79afb054e287c0d5c5c00 (patch)
treed12628b05bde6dc936a11795ea1a48c2de303768
parent044f937a73dc9a28c36a6c87d55c2211247e7d63 (diff)
downloadgo-ff82cc971aabd113f3b79afb054e287c0d5c5c00.tar.gz
go-ff82cc971aabd113f3b79afb054e287c0d5c5c00.zip
os: force consistent mtime before running fstest on directory on Windows
FindFileNext sometimes returns a different mtime than looking at the file directly, because the MFT on NTFS is written to lazily. In order to keep these in sync, we use GetFileInformationByHandle to get the actual mtime, and then write it back to the file explicitly. Fixes #42637. Change-Id: I774016d3ac55d0dc9b0f9c1b681516c33ba0d28a Reviewed-on: https://go-review.googlesource.com/c/go/+/285720 Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Bryan C. Mills <bcmills@google.com> Trust: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--src/os/os_test.go27
1 files changed, 27 insertions, 0 deletions
diff --git a/src/os/os_test.go b/src/os/os_test.go
index 698dbca91e..ee54b4aba1 100644
--- a/src/os/os_test.go
+++ b/src/os/os_test.go
@@ -11,6 +11,7 @@ import (
"fmt"
"internal/testenv"
"io"
+ "io/fs"
"os"
. "os"
osexec "os/exec"
@@ -2689,6 +2690,32 @@ func TestOpenFileKeepsPermissions(t *testing.T) {
}
func TestDirFS(t *testing.T) {
+ // On Windows, we force the MFT to update by reading the actual metadata from GetFileInformationByHandle and then
+ // explicitly setting that. Otherwise it might get out of sync with FindFirstFile. See golang.org/issues/42637.
+ if runtime.GOOS == "windows" {
+ if err := filepath.WalkDir("./testdata/dirfs", func(path string, d fs.DirEntry, err error) error {
+ if err != nil {
+ t.Fatal(err)
+ }
+ info, err := d.Info()
+ if err != nil {
+ t.Fatal(err)
+ }
+ stat, err := Stat(path) // This uses GetFileInformationByHandle internally.
+ if err != nil {
+ t.Fatal(err)
+ }
+ if stat.ModTime() == info.ModTime() {
+ return nil
+ }
+ if err := Chtimes(path, stat.ModTime(), stat.ModTime()); err != nil {
+ t.Log(err) // We only log, not die, in case the test directory is not writable.
+ }
+ return nil
+ }); err != nil {
+ t.Fatal(err)
+ }
+ }
if err := fstest.TestFS(DirFS("./testdata/dirfs"), "a", "b", "dir/x"); err != nil {
t.Fatal(err)
}