forked from ro-ag/posix
-
Notifications
You must be signed in to change notification settings - Fork 0
/
shm_open_darwin.go
189 lines (159 loc) · 4.37 KB
/
shm_open_darwin.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
package posix
import (
"crypto/md5"
"encoding/hex"
"fmt"
"syscall"
"time"
"unsafe"
)
/* -------------------------------------------------------------------------------------------------------------------*/
func newName(name string) string {
unique := ""
n := fmt.Sprintf("%d.%s", time.Now().UnixNano(), name)
x := md5.Sum([]byte(n))
s := hex.EncodeToString(x[:])
unique = _MFD_NAME_PREFIX + s[len(_MFD_NAME_PREFIX)+1:]
return unique
}
func memfdCreate(name string, flags int) (fd int, err error) {
fd = -1
if flags&MFD_HUGETLB == 0 {
if flags & ^_MFD_ALL_FLAGS != 0 {
return fd, EINVAL
}
} else {
/* Allow huge page size encoding in flags. */
if flags & ^(_MFD_ALL_FLAGS|(_MFD_HUGE_MASK<<_MFD_HUGE_SHIFT)) != 0 {
return fd, EINVAL
}
}
/* length includes terminating zero */
nameLen := len(name)
if nameLen <= 0 {
return fd, EFAULT
}
if nameLen > _MFD_NAME_MAX_LEN {
return fd, EINVAL
}
unique := newName(name)
for {
if fd, err = shmOpen(unique, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, S_IRUSR|S_IWUSR|S_IRGRP); err != nil {
if err != syscall.EEXIST {
return -1, err
} else {
unique = newName(name)
}
} else {
break
}
}
if flags&MFD_CLOEXEC == 0 {
/* Remove Flag FD_CLOEXEC which deletes the file if it needs to be passed to another process */
if err = remCloseOnExec(fd); err != nil {
goto unlinking
}
}
/* Delete shmName but keep the file descriptor */
if err = shmUnlink(unique); err != nil {
goto closing
}
return
unlinking:
_ = shmUnlink(unique)
closing:
_ = Close(fd)
fd = -1
return
}
//goland:noinspection GoSnakeCaseUsage
const (
_MFD_NAME_PREFIX = "memfd:"
_MFD_NAME_PREFIX_LEN = 10
_MFD_NAME_MAX_LEN = syscall.NAME_MAX - _MFD_NAME_PREFIX_LEN
_MFD_ALL_FLAGS = MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_HUGETLB
_HUGETLB_FLAG_ENCODE_SHIFT = 26
_HUGETLB_FLAG_ENCODE_MASK = 0x3
_MFD_HUGE_SHIFT = _HUGETLB_FLAG_ENCODE_SHIFT
_MFD_HUGE_MASK = _HUGETLB_FLAG_ENCODE_MASK
)
/* -------------------------------------------------------------------------------------------------------------------*/
func ShmAnonymous() (fd int, err error) {
fd = -1
name := "shm_anon"
unique := newName(name)
for {
if fd, err = shmOpen(unique, O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW, S_IRUSR|S_IWUSR|S_IRGRP); err != nil {
if err != syscall.EEXIST {
return -1, err
} else {
unique = newName(name)
}
} else {
break
}
}
if err != nil {
return
}
/* Delete shmName but keep the file descriptor */
if err = shmUnlink(unique); err != nil {
goto closing
}
/* Remove Flag FD_CLOEXEC which deletes the file if it needs to be passed to another process */
if err = remCloseOnExec(fd); err != nil {
goto closing
}
return
closing:
Close(fd)
fd = -1
return
}
/* -------------------------------------------------------------------------------------------------------------------*/
func remCloseOnExec(fd int) (err error) {
var arg int
if arg, err = Fcntl(fd, F_GETFD, 0); err != nil {
_ = Close(fd)
return
}
arg &^= FD_CLOEXEC // Clear the close-on-exec flag.
if arg, err = Fcntl(fd, F_SETFD, arg); err != nil {
_ = Close(fd)
return
}
return
}
/* -------------------------------------------------------------------------------------------------------------------*/
func shmOpen(path string, oflag int, mode uint32) (fd int, err error) {
var _p0 *byte
_p0, err = syscall.BytePtrFromString(path)
if err != nil {
return
}
r0, _, e1 := syscall_syscall(libc_shm_open_trampoline_addr,
uintptr(unsafe.Pointer(_p0)), uintptr(oflag), uintptr(mode))
fd = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_shm_open_trampoline_addr uintptr
//go:cgo_import_dynamic libc_shm_open shm_open "/usr/lib/libSystem.B.dylib"
/* -------------------------------------------------------------------------------------------------------------------*/
func shmUnlink(path string) (err error) {
var _p0 *byte
_p0, err = syscall.BytePtrFromString(path)
if err != nil {
return
}
_, _, e1 := syscall_syscall(libc_shm_unlink_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
var libc_shm_unlink_trampoline_addr uintptr
//go:cgo_import_dynamic libc_shm_unlink shm_unlink "/usr/lib/libSystem.B.dylib"
/* -------------------------------------------------------------------------------------------------------------------*/