1
0
mirror of https://github.com/golang/go synced 2024-11-23 00:40:08 -07:00

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 <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
This commit is contained in:
qmuntal 2024-02-07 17:40:24 +01:00 committed by Quim Muntal
parent 4a7f3ac8eb
commit 628b1015b9
3 changed files with 45 additions and 17 deletions

View File

@ -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
)

View File

@ -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)
}
}

View File

@ -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