]> Cypherpunks repositories - gostls13.git/commitdiff
os: support reading empty root directories on Windows
authorqmuntal <quimmuntal@gmail.com>
Tue, 4 Jul 2023 11:39:41 +0000 (13:39 +0200)
committerQuim Muntal <quimmuntal@gmail.com>
Fri, 7 Jul 2023 22:02:26 +0000 (22:02 +0000)
GetFileInformationByHandleEx can return `ERROR_FILE_NOT_FOUND` when no
files were found in a root directory, as per MS-FSA 2.1.5.6.3 [1].

This error code should not be treated as an error, but rather as an
indication that no files were found, in which case `readdir` should
return an empty slice.

This CL doesn't add any test as it is difficult to trigger this error
code. Empty root directories created using Windows utilities such as
`net use` always report at least the optional `.` and `..` entries.
A reproducer is provided in #61159, but it requires WinFSP to be
installed.

Fixes #61159

[1] https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fsa/fa8194e0-53ec-413b-8315-e8fa85396fd8

Change-Id: Id46452030f5355c292e5b0abbf5e22af434a84d2
Reviewed-on: https://go-review.googlesource.com/c/go/+/507775
Reviewed-by: Nick Craig-Wood <nickcw@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
src/os/dir_windows.go

index 7792d030404a8997aee0c942fc706884f3849b09..1724af58d576ffe8c3388b2702e58340874d3712 100644 (file)
@@ -84,6 +84,18 @@ func (file *File) readdir(n int, mode readdirMode) (names []string, dirents []Di
                                if err == syscall.ERROR_NO_MORE_FILES {
                                        break
                                }
+                               if infoClass == windows.FileIdBothDirectoryRestartInfo && err == syscall.ERROR_FILE_NOT_FOUND {
+                                       // GetFileInformationByHandleEx doesn't document the return error codes when the info class is FileIdBothDirectoryRestartInfo,
+                                       // but MS-FSA 2.1.5.6.3 [1] specifies that the underlying file system driver should return STATUS_NO_SUCH_FILE when
+                                       // reading an empty root directory, which is mapped to ERROR_FILE_NOT_FOUND by Windows.
+                                       // Note that some file system drivers may never return this error code, as the spec allows to return the "." and ".."
+                                       // entries in such cases, making the directory appear non-empty.
+                                       // The chances of false positive are very low, as we know that the directory exists, else GetVolumeInformationByHandle
+                                       // would have failed, and that the handle is still valid, as we haven't closed it.
+                                       // See go.dev/issue/61159.
+                                       // [1] https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fsa/fa8194e0-53ec-413b-8315-e8fa85396fd8
+                                       break
+                               }
                                if s, _ := file.Stat(); s != nil && !s.IsDir() {
                                        err = &PathError{Op: "readdir", Path: file.name, Err: syscall.ENOTDIR}
                                } else {