Skip to content

Commit

Permalink
os: force consistent mtime before running fstest on directory on Windows
Browse files Browse the repository at this point in the history
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 <[email protected]>
TryBot-Result: Go Bot <[email protected]>
Reviewed-by: Bryan C. Mills <[email protected]>
Trust: Jason A. Donenfeld <[email protected]>
  • Loading branch information
zx2c4 committed Jan 25, 2021
1 parent 044f937 commit ff82cc9
Showing 1 changed file with 27 additions and 0 deletions.
27 changes: 27 additions & 0 deletions src/os/os_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"fmt"
"internal/testenv"
"io"
"io/fs"
"os"
. "os"
osexec "os/exec"
Expand Down Expand Up @@ -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)
}
Expand Down

0 comments on commit ff82cc9

Please sign in to comment.