From 628b1015b972eabcc0a678ab69a74601239c40a4 Mon Sep 17 00:00:00 2001 From: qmuntal Date: Wed, 7 Feb 2024 17:40:24 +0100 Subject: [PATCH] os: add os.ModeSocket support to os.Stat on windows Unix sockets are identified by the IO_REPARSE_TAG_AF_UNIX reparse tag. Teach fileStat.Mode() to recognize this tag and set the os.ModeSocket bit in such case. Note that there is a bug starting in Windows 19H1 until 20H1 that makes the IO_REPARSE_TAG_AF_UNIX tag not being set for unix sockets. This CL doesn't provide a workaround for this bug. Fixes #33357. Change-Id: Iea8f24b20672c8d4b03f55ef298d128431dc3fac Reviewed-on: https://go-review.googlesource.com/c/go/+/561937 LUCI-TryBot-Result: Go LUCI Reviewed-by: Alex Brainman Reviewed-by: David Chase Reviewed-by: Bryan Mills --- .../syscall/windows/reparse_windows.go | 3 ++ src/net/unixsock_windows_test.go | 20 ++++++++++ src/os/types_windows.go | 39 +++++++++++-------- 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/src/internal/syscall/windows/reparse_windows.go b/src/internal/syscall/windows/reparse_windows.go index 02f32c6752592..241dd523c5411 100644 --- a/src/internal/syscall/windows/reparse_windows.go +++ b/src/internal/syscall/windows/reparse_windows.go @@ -9,10 +9,13 @@ import ( "unsafe" ) +// Reparse tag values are taken from +// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/c8e77b37-3909-4fe6-a4ea-2b9d423b1ee4 const ( FSCTL_SET_REPARSE_POINT = 0x000900A4 IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003 IO_REPARSE_TAG_DEDUP = 0x80000013 + IO_REPARSE_TAG_AF_UNIX = 0x80000023 SYMLINK_FLAG_RELATIVE = 1 ) diff --git a/src/net/unixsock_windows_test.go b/src/net/unixsock_windows_test.go index d541d89f78c1e..b3e2260d587b0 100644 --- a/src/net/unixsock_windows_test.go +++ b/src/net/unixsock_windows_test.go @@ -95,3 +95,23 @@ func TestUnixConnLocalWindows(t *testing.T) { } } } + +func TestModeSocket(t *testing.T) { + addr := testUnixAddr(t) + + l, err := Listen("unix", addr) + if err != nil { + t.Fatal(err) + } + defer l.Close() + + stat, err := os.Stat(addr) + if err != nil { + t.Fatal(err) + } + + mode := stat.Mode() + if mode&os.ModeSocket == 0 { + t.Fatalf("%v should have ModeSocket", mode) + } +} diff --git a/src/os/types_windows.go b/src/os/types_windows.go index 6b9fef6c123f6..73433556968d9 100644 --- a/src/os/types_windows.go +++ b/src/os/types_windows.go @@ -184,23 +184,28 @@ func (fs *fileStat) Mode() (m FileMode) { case syscall.FILE_TYPE_CHAR: m |= ModeDevice | ModeCharDevice } - if fs.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 && m&ModeType == 0 { - if fs.ReparseTag == windows.IO_REPARSE_TAG_DEDUP { - // If the Data Deduplication service is enabled on Windows Server, its - // Optimization job may convert regular files to IO_REPARSE_TAG_DEDUP - // whenever that job runs. - // - // However, DEDUP reparse points remain similar in most respects to - // regular files: they continue to support random-access reads and writes - // of persistent data, and they shouldn't add unexpected latency or - // unavailability in the way that a network filesystem might. - // - // Go programs may use ModeIrregular to filter out unusual files (such as - // raw device files on Linux, POSIX FIFO special files, and so on), so - // to avoid files changing unpredictably from regular to irregular we will - // consider DEDUP files to be close enough to regular to treat as such. - } else { - m |= ModeIrregular + if fs.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 { + if fs.ReparseTag == windows.IO_REPARSE_TAG_AF_UNIX { + m |= ModeSocket + } + if m&ModeType == 0 { + if fs.ReparseTag == windows.IO_REPARSE_TAG_DEDUP { + // If the Data Deduplication service is enabled on Windows Server, its + // Optimization job may convert regular files to IO_REPARSE_TAG_DEDUP + // whenever that job runs. + // + // However, DEDUP reparse points remain similar in most respects to + // regular files: they continue to support random-access reads and writes + // of persistent data, and they shouldn't add unexpected latency or + // unavailability in the way that a network filesystem might. + // + // Go programs may use ModeIrregular to filter out unusual files (such as + // raw device files on Linux, POSIX FIFO special files, and so on), so + // to avoid files changing unpredictably from regular to irregular we will + // consider DEDUP files to be close enough to regular to treat as such. + } else { + m |= ModeIrregular + } } } return m