1
2
3
4
5 package unix
6
7 import (
8 "runtime"
9 "sync"
10 "syscall"
11 "unsafe"
12 )
13
14
15
16 var procUname uintptr
17
18
19 type utsname struct {
20 Sysname [257]byte
21 Nodename [257]byte
22 Release [257]byte
23 Version [257]byte
24 Machine [257]byte
25 }
26
27
28
29
30 func KernelVersion() (major int, minor int) {
31 var un utsname
32 _, _, errno := rawSyscall6(uintptr(unsafe.Pointer(&procUname)), 1, uintptr(unsafe.Pointer(&un)), 0, 0, 0, 0, 0)
33 if errno != 0 {
34 return 0, 0
35 }
36
37
38
39
40 ver := un.Version[:]
41 if runtime.GOOS == "illumos" {
42
43
44
45
46 ver = un.Release[:]
47 }
48
49 parseNext := func() (n int) {
50 for i, c := range ver {
51 if c == '.' {
52 ver = ver[i+1:]
53 return
54 }
55 if '0' <= c && c <= '9' {
56 n = n*10 + int(c-'0')
57 }
58 }
59 ver = nil
60 return
61 }
62
63 major = parseNext()
64 minor = parseNext()
65
66 return
67 }
68
69
70
71 var SupportSockNonblockCloexec = sync.OnceValue(func() bool {
72
73 s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, 0)
74 if err == nil {
75 syscall.Close(s)
76 return true
77 }
78 if err != syscall.EPROTONOSUPPORT && err != syscall.EINVAL {
79
80 major, minor := KernelVersion()
81 if runtime.GOOS == "illumos" {
82 return major > 5 || (major == 5 && minor >= 11)
83 }
84 return major > 11 || (major == 11 && minor >= 4)
85 }
86 return false
87 })
88
89
90 var SupportAccept4 = sync.OnceValue(func() bool {
91 for {
92
93 _, _, err := syscall.Accept4(0, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC)
94 if err == syscall.EINTR {
95 continue
96 }
97 return err != syscall.ENOSYS
98 }
99 })
100
101
102
103 var SupportTCPKeepAliveIdleIntvlCNT = sync.OnceValue(func() bool {
104 major, minor := KernelVersion()
105 return major > 11 || (major == 11 && minor >= 4)
106 })
107
View as plain text