diff options
author | Alex Pilon <apilon@hashicorp.com> | 2019-02-22 18:24:37 -0500 |
---|---|---|
committer | Alex Pilon <apilon@hashicorp.com> | 2019-02-22 18:24:37 -0500 |
commit | 15c0b25d011f37e7c20aeca9eaf461f78285b8d9 (patch) | |
tree | 255c250a5c9d4801c74092d33b7337d8c14438ff /vendor/golang.org/x/sys/unix/syscall_linux.go | |
parent | 07971ca38143c5faf951d152fba370ddcbe26ad5 (diff) | |
download | terraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.tar.gz terraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.tar.zst terraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.zip |
deps: github.com/hashicorp/terraform@sdk-v0.11-with-go-modules
Updated via: go get github.com/hashicorp/terraform@sdk-v0.11-with-go-modules and go mod tidy
Diffstat (limited to 'vendor/golang.org/x/sys/unix/syscall_linux.go')
-rw-r--r-- | vendor/golang.org/x/sys/unix/syscall_linux.go | 1628 |
1 files changed, 1628 insertions, 0 deletions
diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go new file mode 100644 index 0000000..84aa8ea --- /dev/null +++ b/vendor/golang.org/x/sys/unix/syscall_linux.go | |||
@@ -0,0 +1,1628 @@ | |||
1 | // Copyright 2009 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | // Linux system calls. | ||
6 | // This file is compiled as ordinary Go code, | ||
7 | // but it is also input to mksyscall, | ||
8 | // which parses the //sys lines and generates system call stubs. | ||
9 | // Note that sometimes we use a lowercase //sys name and | ||
10 | // wrap it in our own nicer implementation. | ||
11 | |||
12 | package unix | ||
13 | |||
14 | import ( | ||
15 | "syscall" | ||
16 | "unsafe" | ||
17 | ) | ||
18 | |||
19 | /* | ||
20 | * Wrapped | ||
21 | */ | ||
22 | |||
23 | func Access(path string, mode uint32) (err error) { | ||
24 | return Faccessat(AT_FDCWD, path, mode, 0) | ||
25 | } | ||
26 | |||
27 | func Chmod(path string, mode uint32) (err error) { | ||
28 | return Fchmodat(AT_FDCWD, path, mode, 0) | ||
29 | } | ||
30 | |||
31 | func Chown(path string, uid int, gid int) (err error) { | ||
32 | return Fchownat(AT_FDCWD, path, uid, gid, 0) | ||
33 | } | ||
34 | |||
35 | func Creat(path string, mode uint32) (fd int, err error) { | ||
36 | return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode) | ||
37 | } | ||
38 | |||
39 | //sys fchmodat(dirfd int, path string, mode uint32) (err error) | ||
40 | |||
41 | func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) { | ||
42 | // Linux fchmodat doesn't support the flags parameter. Mimick glibc's behavior | ||
43 | // and check the flags. Otherwise the mode would be applied to the symlink | ||
44 | // destination which is not what the user expects. | ||
45 | if flags&^AT_SYMLINK_NOFOLLOW != 0 { | ||
46 | return EINVAL | ||
47 | } else if flags&AT_SYMLINK_NOFOLLOW != 0 { | ||
48 | return EOPNOTSUPP | ||
49 | } | ||
50 | return fchmodat(dirfd, path, mode) | ||
51 | } | ||
52 | |||
53 | //sys ioctl(fd int, req uint, arg uintptr) (err error) | ||
54 | |||
55 | // ioctl itself should not be exposed directly, but additional get/set | ||
56 | // functions for specific types are permissible. | ||
57 | |||
58 | // IoctlSetInt performs an ioctl operation which sets an integer value | ||
59 | // on fd, using the specified request number. | ||
60 | func IoctlSetInt(fd int, req uint, value int) error { | ||
61 | return ioctl(fd, req, uintptr(value)) | ||
62 | } | ||
63 | |||
64 | func ioctlSetWinsize(fd int, req uint, value *Winsize) error { | ||
65 | return ioctl(fd, req, uintptr(unsafe.Pointer(value))) | ||
66 | } | ||
67 | |||
68 | func ioctlSetTermios(fd int, req uint, value *Termios) error { | ||
69 | return ioctl(fd, req, uintptr(unsafe.Pointer(value))) | ||
70 | } | ||
71 | |||
72 | // IoctlGetInt performs an ioctl operation which gets an integer value | ||
73 | // from fd, using the specified request number. | ||
74 | func IoctlGetInt(fd int, req uint) (int, error) { | ||
75 | var value int | ||
76 | err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) | ||
77 | return value, err | ||
78 | } | ||
79 | |||
80 | func IoctlGetWinsize(fd int, req uint) (*Winsize, error) { | ||
81 | var value Winsize | ||
82 | err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) | ||
83 | return &value, err | ||
84 | } | ||
85 | |||
86 | func IoctlGetTermios(fd int, req uint) (*Termios, error) { | ||
87 | var value Termios | ||
88 | err := ioctl(fd, req, uintptr(unsafe.Pointer(&value))) | ||
89 | return &value, err | ||
90 | } | ||
91 | |||
92 | //sys Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) | ||
93 | |||
94 | func Link(oldpath string, newpath string) (err error) { | ||
95 | return Linkat(AT_FDCWD, oldpath, AT_FDCWD, newpath, 0) | ||
96 | } | ||
97 | |||
98 | func Mkdir(path string, mode uint32) (err error) { | ||
99 | return Mkdirat(AT_FDCWD, path, mode) | ||
100 | } | ||
101 | |||
102 | func Mknod(path string, mode uint32, dev int) (err error) { | ||
103 | return Mknodat(AT_FDCWD, path, mode, dev) | ||
104 | } | ||
105 | |||
106 | func Open(path string, mode int, perm uint32) (fd int, err error) { | ||
107 | return openat(AT_FDCWD, path, mode|O_LARGEFILE, perm) | ||
108 | } | ||
109 | |||
110 | //sys openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) | ||
111 | |||
112 | func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) { | ||
113 | return openat(dirfd, path, flags|O_LARGEFILE, mode) | ||
114 | } | ||
115 | |||
116 | //sys ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) | ||
117 | |||
118 | func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { | ||
119 | if len(fds) == 0 { | ||
120 | return ppoll(nil, 0, timeout, sigmask) | ||
121 | } | ||
122 | return ppoll(&fds[0], len(fds), timeout, sigmask) | ||
123 | } | ||
124 | |||
125 | //sys Readlinkat(dirfd int, path string, buf []byte) (n int, err error) | ||
126 | |||
127 | func Readlink(path string, buf []byte) (n int, err error) { | ||
128 | return Readlinkat(AT_FDCWD, path, buf) | ||
129 | } | ||
130 | |||
131 | func Rename(oldpath string, newpath string) (err error) { | ||
132 | return Renameat(AT_FDCWD, oldpath, AT_FDCWD, newpath) | ||
133 | } | ||
134 | |||
135 | func Rmdir(path string) error { | ||
136 | return Unlinkat(AT_FDCWD, path, AT_REMOVEDIR) | ||
137 | } | ||
138 | |||
139 | //sys Symlinkat(oldpath string, newdirfd int, newpath string) (err error) | ||
140 | |||
141 | func Symlink(oldpath string, newpath string) (err error) { | ||
142 | return Symlinkat(oldpath, AT_FDCWD, newpath) | ||
143 | } | ||
144 | |||
145 | func Unlink(path string) error { | ||
146 | return Unlinkat(AT_FDCWD, path, 0) | ||
147 | } | ||
148 | |||
149 | //sys Unlinkat(dirfd int, path string, flags int) (err error) | ||
150 | |||
151 | func Utimes(path string, tv []Timeval) error { | ||
152 | if tv == nil { | ||
153 | err := utimensat(AT_FDCWD, path, nil, 0) | ||
154 | if err != ENOSYS { | ||
155 | return err | ||
156 | } | ||
157 | return utimes(path, nil) | ||
158 | } | ||
159 | if len(tv) != 2 { | ||
160 | return EINVAL | ||
161 | } | ||
162 | var ts [2]Timespec | ||
163 | ts[0] = NsecToTimespec(TimevalToNsec(tv[0])) | ||
164 | ts[1] = NsecToTimespec(TimevalToNsec(tv[1])) | ||
165 | err := utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) | ||
166 | if err != ENOSYS { | ||
167 | return err | ||
168 | } | ||
169 | return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) | ||
170 | } | ||
171 | |||
172 | //sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error) | ||
173 | |||
174 | func UtimesNano(path string, ts []Timespec) error { | ||
175 | if ts == nil { | ||
176 | err := utimensat(AT_FDCWD, path, nil, 0) | ||
177 | if err != ENOSYS { | ||
178 | return err | ||
179 | } | ||
180 | return utimes(path, nil) | ||
181 | } | ||
182 | if len(ts) != 2 { | ||
183 | return EINVAL | ||
184 | } | ||
185 | err := utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0) | ||
186 | if err != ENOSYS { | ||
187 | return err | ||
188 | } | ||
189 | // If the utimensat syscall isn't available (utimensat was added to Linux | ||
190 | // in 2.6.22, Released, 8 July 2007) then fall back to utimes | ||
191 | var tv [2]Timeval | ||
192 | for i := 0; i < 2; i++ { | ||
193 | tv[i] = NsecToTimeval(TimespecToNsec(ts[i])) | ||
194 | } | ||
195 | return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) | ||
196 | } | ||
197 | |||
198 | func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error { | ||
199 | if ts == nil { | ||
200 | return utimensat(dirfd, path, nil, flags) | ||
201 | } | ||
202 | if len(ts) != 2 { | ||
203 | return EINVAL | ||
204 | } | ||
205 | return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags) | ||
206 | } | ||
207 | |||
208 | func Futimesat(dirfd int, path string, tv []Timeval) error { | ||
209 | if tv == nil { | ||
210 | return futimesat(dirfd, path, nil) | ||
211 | } | ||
212 | if len(tv) != 2 { | ||
213 | return EINVAL | ||
214 | } | ||
215 | return futimesat(dirfd, path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) | ||
216 | } | ||
217 | |||
218 | func Futimes(fd int, tv []Timeval) (err error) { | ||
219 | // Believe it or not, this is the best we can do on Linux | ||
220 | // (and is what glibc does). | ||
221 | return Utimes("/proc/self/fd/"+itoa(fd), tv) | ||
222 | } | ||
223 | |||
224 | const ImplementsGetwd = true | ||
225 | |||
226 | //sys Getcwd(buf []byte) (n int, err error) | ||
227 | |||
228 | func Getwd() (wd string, err error) { | ||
229 | var buf [PathMax]byte | ||
230 | n, err := Getcwd(buf[0:]) | ||
231 | if err != nil { | ||
232 | return "", err | ||
233 | } | ||
234 | // Getcwd returns the number of bytes written to buf, including the NUL. | ||
235 | if n < 1 || n > len(buf) || buf[n-1] != 0 { | ||
236 | return "", EINVAL | ||
237 | } | ||
238 | return string(buf[0 : n-1]), nil | ||
239 | } | ||
240 | |||
241 | func Getgroups() (gids []int, err error) { | ||
242 | n, err := getgroups(0, nil) | ||
243 | if err != nil { | ||
244 | return nil, err | ||
245 | } | ||
246 | if n == 0 { | ||
247 | return nil, nil | ||
248 | } | ||
249 | |||
250 | // Sanity check group count. Max is 1<<16 on Linux. | ||
251 | if n < 0 || n > 1<<20 { | ||
252 | return nil, EINVAL | ||
253 | } | ||
254 | |||
255 | a := make([]_Gid_t, n) | ||
256 | n, err = getgroups(n, &a[0]) | ||
257 | if err != nil { | ||
258 | return nil, err | ||
259 | } | ||
260 | gids = make([]int, n) | ||
261 | for i, v := range a[0:n] { | ||
262 | gids[i] = int(v) | ||
263 | } | ||
264 | return | ||
265 | } | ||
266 | |||
267 | func Setgroups(gids []int) (err error) { | ||
268 | if len(gids) == 0 { | ||
269 | return setgroups(0, nil) | ||
270 | } | ||
271 | |||
272 | a := make([]_Gid_t, len(gids)) | ||
273 | for i, v := range gids { | ||
274 | a[i] = _Gid_t(v) | ||
275 | } | ||
276 | return setgroups(len(a), &a[0]) | ||
277 | } | ||
278 | |||
279 | type WaitStatus uint32 | ||
280 | |||
281 | // Wait status is 7 bits at bottom, either 0 (exited), | ||
282 | // 0x7F (stopped), or a signal number that caused an exit. | ||
283 | // The 0x80 bit is whether there was a core dump. | ||
284 | // An extra number (exit code, signal causing a stop) | ||
285 | // is in the high bits. At least that's the idea. | ||
286 | // There are various irregularities. For example, the | ||
287 | // "continued" status is 0xFFFF, distinguishing itself | ||
288 | // from stopped via the core dump bit. | ||
289 | |||
290 | const ( | ||
291 | mask = 0x7F | ||
292 | core = 0x80 | ||
293 | exited = 0x00 | ||
294 | stopped = 0x7F | ||
295 | shift = 8 | ||
296 | ) | ||
297 | |||
298 | func (w WaitStatus) Exited() bool { return w&mask == exited } | ||
299 | |||
300 | func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != exited } | ||
301 | |||
302 | func (w WaitStatus) Stopped() bool { return w&0xFF == stopped } | ||
303 | |||
304 | func (w WaitStatus) Continued() bool { return w == 0xFFFF } | ||
305 | |||
306 | func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 } | ||
307 | |||
308 | func (w WaitStatus) ExitStatus() int { | ||
309 | if !w.Exited() { | ||
310 | return -1 | ||
311 | } | ||
312 | return int(w>>shift) & 0xFF | ||
313 | } | ||
314 | |||
315 | func (w WaitStatus) Signal() syscall.Signal { | ||
316 | if !w.Signaled() { | ||
317 | return -1 | ||
318 | } | ||
319 | return syscall.Signal(w & mask) | ||
320 | } | ||
321 | |||
322 | func (w WaitStatus) StopSignal() syscall.Signal { | ||
323 | if !w.Stopped() { | ||
324 | return -1 | ||
325 | } | ||
326 | return syscall.Signal(w>>shift) & 0xFF | ||
327 | } | ||
328 | |||
329 | func (w WaitStatus) TrapCause() int { | ||
330 | if w.StopSignal() != SIGTRAP { | ||
331 | return -1 | ||
332 | } | ||
333 | return int(w>>shift) >> 8 | ||
334 | } | ||
335 | |||
336 | //sys wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) | ||
337 | |||
338 | func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { | ||
339 | var status _C_int | ||
340 | wpid, err = wait4(pid, &status, options, rusage) | ||
341 | if wstatus != nil { | ||
342 | *wstatus = WaitStatus(status) | ||
343 | } | ||
344 | return | ||
345 | } | ||
346 | |||
347 | func Mkfifo(path string, mode uint32) error { | ||
348 | return Mknod(path, mode|S_IFIFO, 0) | ||
349 | } | ||
350 | |||
351 | func Mkfifoat(dirfd int, path string, mode uint32) error { | ||
352 | return Mknodat(dirfd, path, mode|S_IFIFO, 0) | ||
353 | } | ||
354 | |||
355 | func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { | ||
356 | if sa.Port < 0 || sa.Port > 0xFFFF { | ||
357 | return nil, 0, EINVAL | ||
358 | } | ||
359 | sa.raw.Family = AF_INET | ||
360 | p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) | ||
361 | p[0] = byte(sa.Port >> 8) | ||
362 | p[1] = byte(sa.Port) | ||
363 | for i := 0; i < len(sa.Addr); i++ { | ||
364 | sa.raw.Addr[i] = sa.Addr[i] | ||
365 | } | ||
366 | return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil | ||
367 | } | ||
368 | |||
369 | func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) { | ||
370 | if sa.Port < 0 || sa.Port > 0xFFFF { | ||
371 | return nil, 0, EINVAL | ||
372 | } | ||
373 | sa.raw.Family = AF_INET6 | ||
374 | p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port)) | ||
375 | p[0] = byte(sa.Port >> 8) | ||
376 | p[1] = byte(sa.Port) | ||
377 | sa.raw.Scope_id = sa.ZoneId | ||
378 | for i := 0; i < len(sa.Addr); i++ { | ||
379 | sa.raw.Addr[i] = sa.Addr[i] | ||
380 | } | ||
381 | return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil | ||
382 | } | ||
383 | |||
384 | func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { | ||
385 | name := sa.Name | ||
386 | n := len(name) | ||
387 | if n >= len(sa.raw.Path) { | ||
388 | return nil, 0, EINVAL | ||
389 | } | ||
390 | sa.raw.Family = AF_UNIX | ||
391 | for i := 0; i < n; i++ { | ||
392 | sa.raw.Path[i] = int8(name[i]) | ||
393 | } | ||
394 | // length is family (uint16), name, NUL. | ||
395 | sl := _Socklen(2) | ||
396 | if n > 0 { | ||
397 | sl += _Socklen(n) + 1 | ||
398 | } | ||
399 | if sa.raw.Path[0] == '@' { | ||
400 | sa.raw.Path[0] = 0 | ||
401 | // Don't count trailing NUL for abstract address. | ||
402 | sl-- | ||
403 | } | ||
404 | |||
405 | return unsafe.Pointer(&sa.raw), sl, nil | ||
406 | } | ||
407 | |||
408 | // SockaddrLinklayer implements the Sockaddr interface for AF_PACKET type sockets. | ||
409 | type SockaddrLinklayer struct { | ||
410 | Protocol uint16 | ||
411 | Ifindex int | ||
412 | Hatype uint16 | ||
413 | Pkttype uint8 | ||
414 | Halen uint8 | ||
415 | Addr [8]byte | ||
416 | raw RawSockaddrLinklayer | ||
417 | } | ||
418 | |||
419 | func (sa *SockaddrLinklayer) sockaddr() (unsafe.Pointer, _Socklen, error) { | ||
420 | if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff { | ||
421 | return nil, 0, EINVAL | ||
422 | } | ||
423 | sa.raw.Family = AF_PACKET | ||
424 | sa.raw.Protocol = sa.Protocol | ||
425 | sa.raw.Ifindex = int32(sa.Ifindex) | ||
426 | sa.raw.Hatype = sa.Hatype | ||
427 | sa.raw.Pkttype = sa.Pkttype | ||
428 | sa.raw.Halen = sa.Halen | ||
429 | for i := 0; i < len(sa.Addr); i++ { | ||
430 | sa.raw.Addr[i] = sa.Addr[i] | ||
431 | } | ||
432 | return unsafe.Pointer(&sa.raw), SizeofSockaddrLinklayer, nil | ||
433 | } | ||
434 | |||
435 | // SockaddrNetlink implements the Sockaddr interface for AF_NETLINK type sockets. | ||
436 | type SockaddrNetlink struct { | ||
437 | Family uint16 | ||
438 | Pad uint16 | ||
439 | Pid uint32 | ||
440 | Groups uint32 | ||
441 | raw RawSockaddrNetlink | ||
442 | } | ||
443 | |||
444 | func (sa *SockaddrNetlink) sockaddr() (unsafe.Pointer, _Socklen, error) { | ||
445 | sa.raw.Family = AF_NETLINK | ||
446 | sa.raw.Pad = sa.Pad | ||
447 | sa.raw.Pid = sa.Pid | ||
448 | sa.raw.Groups = sa.Groups | ||
449 | return unsafe.Pointer(&sa.raw), SizeofSockaddrNetlink, nil | ||
450 | } | ||
451 | |||
452 | // SockaddrHCI implements the Sockaddr interface for AF_BLUETOOTH type sockets | ||
453 | // using the HCI protocol. | ||
454 | type SockaddrHCI struct { | ||
455 | Dev uint16 | ||
456 | Channel uint16 | ||
457 | raw RawSockaddrHCI | ||
458 | } | ||
459 | |||
460 | func (sa *SockaddrHCI) sockaddr() (unsafe.Pointer, _Socklen, error) { | ||
461 | sa.raw.Family = AF_BLUETOOTH | ||
462 | sa.raw.Dev = sa.Dev | ||
463 | sa.raw.Channel = sa.Channel | ||
464 | return unsafe.Pointer(&sa.raw), SizeofSockaddrHCI, nil | ||
465 | } | ||
466 | |||
467 | // SockaddrL2 implements the Sockaddr interface for AF_BLUETOOTH type sockets | ||
468 | // using the L2CAP protocol. | ||
469 | type SockaddrL2 struct { | ||
470 | PSM uint16 | ||
471 | CID uint16 | ||
472 | Addr [6]uint8 | ||
473 | AddrType uint8 | ||
474 | raw RawSockaddrL2 | ||
475 | } | ||
476 | |||
477 | func (sa *SockaddrL2) sockaddr() (unsafe.Pointer, _Socklen, error) { | ||
478 | sa.raw.Family = AF_BLUETOOTH | ||
479 | psm := (*[2]byte)(unsafe.Pointer(&sa.raw.Psm)) | ||
480 | psm[0] = byte(sa.PSM) | ||
481 | psm[1] = byte(sa.PSM >> 8) | ||
482 | for i := 0; i < len(sa.Addr); i++ { | ||
483 | sa.raw.Bdaddr[i] = sa.Addr[len(sa.Addr)-1-i] | ||
484 | } | ||
485 | cid := (*[2]byte)(unsafe.Pointer(&sa.raw.Cid)) | ||
486 | cid[0] = byte(sa.CID) | ||
487 | cid[1] = byte(sa.CID >> 8) | ||
488 | sa.raw.Bdaddr_type = sa.AddrType | ||
489 | return unsafe.Pointer(&sa.raw), SizeofSockaddrL2, nil | ||
490 | } | ||
491 | |||
492 | // SockaddrRFCOMM implements the Sockaddr interface for AF_BLUETOOTH type sockets | ||
493 | // using the RFCOMM protocol. | ||
494 | // | ||
495 | // Server example: | ||
496 | // | ||
497 | // fd, _ := Socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM) | ||
498 | // _ = unix.Bind(fd, &unix.SockaddrRFCOMM{ | ||
499 | // Channel: 1, | ||
500 | // Addr: [6]uint8{0, 0, 0, 0, 0, 0}, // BDADDR_ANY or 00:00:00:00:00:00 | ||
501 | // }) | ||
502 | // _ = Listen(fd, 1) | ||
503 | // nfd, sa, _ := Accept(fd) | ||
504 | // fmt.Printf("conn addr=%v fd=%d", sa.(*unix.SockaddrRFCOMM).Addr, nfd) | ||
505 | // Read(nfd, buf) | ||
506 | // | ||
507 | // Client example: | ||
508 | // | ||
509 | // fd, _ := Socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM) | ||
510 | // _ = Connect(fd, &SockaddrRFCOMM{ | ||
511 | // Channel: 1, | ||
512 | // Addr: [6]byte{0x11, 0x22, 0x33, 0xaa, 0xbb, 0xcc}, // CC:BB:AA:33:22:11 | ||
513 | // }) | ||
514 | // Write(fd, []byte(`hello`)) | ||
515 | type SockaddrRFCOMM struct { | ||
516 | // Addr represents a bluetooth address, byte ordering is little-endian. | ||
517 | Addr [6]uint8 | ||
518 | |||
519 | // Channel is a designated bluetooth channel, only 1-30 are available for use. | ||
520 | // Since Linux 2.6.7 and further zero value is the first available channel. | ||
521 | Channel uint8 | ||
522 | |||
523 | raw RawSockaddrRFCOMM | ||
524 | } | ||
525 | |||
526 | func (sa *SockaddrRFCOMM) sockaddr() (unsafe.Pointer, _Socklen, error) { | ||
527 | sa.raw.Family = AF_BLUETOOTH | ||
528 | sa.raw.Channel = sa.Channel | ||
529 | sa.raw.Bdaddr = sa.Addr | ||
530 | return unsafe.Pointer(&sa.raw), SizeofSockaddrRFCOMM, nil | ||
531 | } | ||
532 | |||
533 | // SockaddrCAN implements the Sockaddr interface for AF_CAN type sockets. | ||
534 | // The RxID and TxID fields are used for transport protocol addressing in | ||
535 | // (CAN_TP16, CAN_TP20, CAN_MCNET, and CAN_ISOTP), they can be left with | ||
536 | // zero values for CAN_RAW and CAN_BCM sockets as they have no meaning. | ||
537 | // | ||
538 | // The SockaddrCAN struct must be bound to the socket file descriptor | ||
539 | // using Bind before the CAN socket can be used. | ||
540 | // | ||
541 | // // Read one raw CAN frame | ||
542 | // fd, _ := Socket(AF_CAN, SOCK_RAW, CAN_RAW) | ||
543 | // addr := &SockaddrCAN{Ifindex: index} | ||
544 | // Bind(fd, addr) | ||
545 | // frame := make([]byte, 16) | ||
546 | // Read(fd, frame) | ||
547 | // | ||
548 | // The full SocketCAN documentation can be found in the linux kernel | ||
549 | // archives at: https://www.kernel.org/doc/Documentation/networking/can.txt | ||
550 | type SockaddrCAN struct { | ||
551 | Ifindex int | ||
552 | RxID uint32 | ||
553 | TxID uint32 | ||
554 | raw RawSockaddrCAN | ||
555 | } | ||
556 | |||
557 | func (sa *SockaddrCAN) sockaddr() (unsafe.Pointer, _Socklen, error) { | ||
558 | if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff { | ||
559 | return nil, 0, EINVAL | ||
560 | } | ||
561 | sa.raw.Family = AF_CAN | ||
562 | sa.raw.Ifindex = int32(sa.Ifindex) | ||
563 | rx := (*[4]byte)(unsafe.Pointer(&sa.RxID)) | ||
564 | for i := 0; i < 4; i++ { | ||
565 | sa.raw.Addr[i] = rx[i] | ||
566 | } | ||
567 | tx := (*[4]byte)(unsafe.Pointer(&sa.TxID)) | ||
568 | for i := 0; i < 4; i++ { | ||
569 | sa.raw.Addr[i+4] = tx[i] | ||
570 | } | ||
571 | return unsafe.Pointer(&sa.raw), SizeofSockaddrCAN, nil | ||
572 | } | ||
573 | |||
574 | // SockaddrALG implements the Sockaddr interface for AF_ALG type sockets. | ||
575 | // SockaddrALG enables userspace access to the Linux kernel's cryptography | ||
576 | // subsystem. The Type and Name fields specify which type of hash or cipher | ||
577 | // should be used with a given socket. | ||
578 | // | ||
579 | // To create a file descriptor that provides access to a hash or cipher, both | ||
580 | // Bind and Accept must be used. Once the setup process is complete, input | ||
581 | // data can be written to the socket, processed by the kernel, and then read | ||
582 | // back as hash output or ciphertext. | ||
583 | // | ||
584 | // Here is an example of using an AF_ALG socket with SHA1 hashing. | ||
585 | // The initial socket setup process is as follows: | ||
586 | // | ||
587 | // // Open a socket to perform SHA1 hashing. | ||
588 | // fd, _ := unix.Socket(unix.AF_ALG, unix.SOCK_SEQPACKET, 0) | ||
589 | // addr := &unix.SockaddrALG{Type: "hash", Name: "sha1"} | ||
590 | // unix.Bind(fd, addr) | ||
591 | // // Note: unix.Accept does not work at this time; must invoke accept() | ||
592 | // // manually using unix.Syscall. | ||
593 | // hashfd, _, _ := unix.Syscall(unix.SYS_ACCEPT, uintptr(fd), 0, 0) | ||
594 | // | ||
595 | // Once a file descriptor has been returned from Accept, it may be used to | ||
596 | // perform SHA1 hashing. The descriptor is not safe for concurrent use, but | ||
597 | // may be re-used repeatedly with subsequent Write and Read operations. | ||
598 | // | ||
599 | // When hashing a small byte slice or string, a single Write and Read may | ||
600 | // be used: | ||
601 | // | ||
602 | // // Assume hashfd is already configured using the setup process. | ||
603 | // hash := os.NewFile(hashfd, "sha1") | ||
604 | // // Hash an input string and read the results. Each Write discards | ||
605 | // // previous hash state. Read always reads the current state. | ||
606 | // b := make([]byte, 20) | ||
607 | // for i := 0; i < 2; i++ { | ||
608 | // io.WriteString(hash, "Hello, world.") | ||
609 | // hash.Read(b) | ||
610 | // fmt.Println(hex.EncodeToString(b)) | ||
611 | // } | ||
612 | // // Output: | ||
613 | // // 2ae01472317d1935a84797ec1983ae243fc6aa28 | ||
614 | // // 2ae01472317d1935a84797ec1983ae243fc6aa28 | ||
615 | // | ||
616 | // For hashing larger byte slices, or byte streams such as those read from | ||
617 | // a file or socket, use Sendto with MSG_MORE to instruct the kernel to update | ||
618 | // the hash digest instead of creating a new one for a given chunk and finalizing it. | ||
619 | // | ||
620 | // // Assume hashfd and addr are already configured using the setup process. | ||
621 | // hash := os.NewFile(hashfd, "sha1") | ||
622 | // // Hash the contents of a file. | ||
623 | // f, _ := os.Open("/tmp/linux-4.10-rc7.tar.xz") | ||
624 | // b := make([]byte, 4096) | ||
625 | // for { | ||
626 | // n, err := f.Read(b) | ||
627 | // if err == io.EOF { | ||
628 | // break | ||
629 | // } | ||
630 | // unix.Sendto(hashfd, b[:n], unix.MSG_MORE, addr) | ||
631 | // } | ||
632 | // hash.Read(b) | ||
633 | // fmt.Println(hex.EncodeToString(b)) | ||
634 | // // Output: 85cdcad0c06eef66f805ecce353bec9accbeecc5 | ||
635 | // | ||
636 | // For more information, see: http://www.chronox.de/crypto-API/crypto/userspace-if.html. | ||
637 | type SockaddrALG struct { | ||
638 | Type string | ||
639 | Name string | ||
640 | Feature uint32 | ||
641 | Mask uint32 | ||
642 | raw RawSockaddrALG | ||
643 | } | ||
644 | |||
645 | func (sa *SockaddrALG) sockaddr() (unsafe.Pointer, _Socklen, error) { | ||
646 | // Leave room for NUL byte terminator. | ||
647 | if len(sa.Type) > 13 { | ||
648 | return nil, 0, EINVAL | ||
649 | } | ||
650 | if len(sa.Name) > 63 { | ||
651 | return nil, 0, EINVAL | ||
652 | } | ||
653 | |||
654 | sa.raw.Family = AF_ALG | ||
655 | sa.raw.Feat = sa.Feature | ||
656 | sa.raw.Mask = sa.Mask | ||
657 | |||
658 | typ, err := ByteSliceFromString(sa.Type) | ||
659 | if err != nil { | ||
660 | return nil, 0, err | ||
661 | } | ||
662 | name, err := ByteSliceFromString(sa.Name) | ||
663 | if err != nil { | ||
664 | return nil, 0, err | ||
665 | } | ||
666 | |||
667 | copy(sa.raw.Type[:], typ) | ||
668 | copy(sa.raw.Name[:], name) | ||
669 | |||
670 | return unsafe.Pointer(&sa.raw), SizeofSockaddrALG, nil | ||
671 | } | ||
672 | |||
673 | // SockaddrVM implements the Sockaddr interface for AF_VSOCK type sockets. | ||
674 | // SockaddrVM provides access to Linux VM sockets: a mechanism that enables | ||
675 | // bidirectional communication between a hypervisor and its guest virtual | ||
676 | // machines. | ||
677 | type SockaddrVM struct { | ||
678 | // CID and Port specify a context ID and port address for a VM socket. | ||
679 | // Guests have a unique CID, and hosts may have a well-known CID of: | ||
680 | // - VMADDR_CID_HYPERVISOR: refers to the hypervisor process. | ||
681 | // - VMADDR_CID_HOST: refers to other processes on the host. | ||
682 | CID uint32 | ||
683 | Port uint32 | ||
684 | raw RawSockaddrVM | ||
685 | } | ||
686 | |||
687 | func (sa *SockaddrVM) sockaddr() (unsafe.Pointer, _Socklen, error) { | ||
688 | sa.raw.Family = AF_VSOCK | ||
689 | sa.raw.Port = sa.Port | ||
690 | sa.raw.Cid = sa.CID | ||
691 | |||
692 | return unsafe.Pointer(&sa.raw), SizeofSockaddrVM, nil | ||
693 | } | ||
694 | |||
695 | type SockaddrXDP struct { | ||
696 | Flags uint16 | ||
697 | Ifindex uint32 | ||
698 | QueueID uint32 | ||
699 | SharedUmemFD uint32 | ||
700 | raw RawSockaddrXDP | ||
701 | } | ||
702 | |||
703 | func (sa *SockaddrXDP) sockaddr() (unsafe.Pointer, _Socklen, error) { | ||
704 | sa.raw.Family = AF_XDP | ||
705 | sa.raw.Flags = sa.Flags | ||
706 | sa.raw.Ifindex = sa.Ifindex | ||
707 | sa.raw.Queue_id = sa.QueueID | ||
708 | sa.raw.Shared_umem_fd = sa.SharedUmemFD | ||
709 | |||
710 | return unsafe.Pointer(&sa.raw), SizeofSockaddrXDP, nil | ||
711 | } | ||
712 | |||
713 | func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { | ||
714 | switch rsa.Addr.Family { | ||
715 | case AF_NETLINK: | ||
716 | pp := (*RawSockaddrNetlink)(unsafe.Pointer(rsa)) | ||
717 | sa := new(SockaddrNetlink) | ||
718 | sa.Family = pp.Family | ||
719 | sa.Pad = pp.Pad | ||
720 | sa.Pid = pp.Pid | ||
721 | sa.Groups = pp.Groups | ||
722 | return sa, nil | ||
723 | |||
724 | case AF_PACKET: | ||
725 | pp := (*RawSockaddrLinklayer)(unsafe.Pointer(rsa)) | ||
726 | sa := new(SockaddrLinklayer) | ||
727 | sa.Protocol = pp.Protocol | ||
728 | sa.Ifindex = int(pp.Ifindex) | ||
729 | sa.Hatype = pp.Hatype | ||
730 | sa.Pkttype = pp.Pkttype | ||
731 | sa.Halen = pp.Halen | ||
732 | for i := 0; i < len(sa.Addr); i++ { | ||
733 | sa.Addr[i] = pp.Addr[i] | ||
734 | } | ||
735 | return sa, nil | ||
736 | |||
737 | case AF_UNIX: | ||
738 | pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa)) | ||
739 | sa := new(SockaddrUnix) | ||
740 | if pp.Path[0] == 0 { | ||
741 | // "Abstract" Unix domain socket. | ||
742 | // Rewrite leading NUL as @ for textual display. | ||
743 | // (This is the standard convention.) | ||
744 | // Not friendly to overwrite in place, | ||
745 | // but the callers below don't care. | ||
746 | pp.Path[0] = '@' | ||
747 | } | ||
748 | |||
749 | // Assume path ends at NUL. | ||
750 | // This is not technically the Linux semantics for | ||
751 | // abstract Unix domain sockets--they are supposed | ||
752 | // to be uninterpreted fixed-size binary blobs--but | ||
753 | // everyone uses this convention. | ||
754 | n := 0 | ||
755 | for n < len(pp.Path) && pp.Path[n] != 0 { | ||
756 | n++ | ||
757 | } | ||
758 | bytes := (*[10000]byte)(unsafe.Pointer(&pp.Path[0]))[0:n] | ||
759 | sa.Name = string(bytes) | ||
760 | return sa, nil | ||
761 | |||
762 | case AF_INET: | ||
763 | pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa)) | ||
764 | sa := new(SockaddrInet4) | ||
765 | p := (*[2]byte)(unsafe.Pointer(&pp.Port)) | ||
766 | sa.Port = int(p[0])<<8 + int(p[1]) | ||
767 | for i := 0; i < len(sa.Addr); i++ { | ||
768 | sa.Addr[i] = pp.Addr[i] | ||
769 | } | ||
770 | return sa, nil | ||
771 | |||
772 | case AF_INET6: | ||
773 | pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa)) | ||
774 | sa := new(SockaddrInet6) | ||
775 | p := (*[2]byte)(unsafe.Pointer(&pp.Port)) | ||
776 | sa.Port = int(p[0])<<8 + int(p[1]) | ||
777 | sa.ZoneId = pp.Scope_id | ||
778 | for i := 0; i < len(sa.Addr); i++ { | ||
779 | sa.Addr[i] = pp.Addr[i] | ||
780 | } | ||
781 | return sa, nil | ||
782 | |||
783 | case AF_VSOCK: | ||
784 | pp := (*RawSockaddrVM)(unsafe.Pointer(rsa)) | ||
785 | sa := &SockaddrVM{ | ||
786 | CID: pp.Cid, | ||
787 | Port: pp.Port, | ||
788 | } | ||
789 | return sa, nil | ||
790 | case AF_BLUETOOTH: | ||
791 | proto, err := GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL) | ||
792 | if err != nil { | ||
793 | return nil, err | ||
794 | } | ||
795 | // only BTPROTO_L2CAP and BTPROTO_RFCOMM can accept connections | ||
796 | switch proto { | ||
797 | case BTPROTO_L2CAP: | ||
798 | pp := (*RawSockaddrL2)(unsafe.Pointer(rsa)) | ||
799 | sa := &SockaddrL2{ | ||
800 | PSM: pp.Psm, | ||
801 | CID: pp.Cid, | ||
802 | Addr: pp.Bdaddr, | ||
803 | AddrType: pp.Bdaddr_type, | ||
804 | } | ||
805 | return sa, nil | ||
806 | case BTPROTO_RFCOMM: | ||
807 | pp := (*RawSockaddrRFCOMM)(unsafe.Pointer(rsa)) | ||
808 | sa := &SockaddrRFCOMM{ | ||
809 | Channel: pp.Channel, | ||
810 | Addr: pp.Bdaddr, | ||
811 | } | ||
812 | return sa, nil | ||
813 | } | ||
814 | case AF_XDP: | ||
815 | pp := (*RawSockaddrXDP)(unsafe.Pointer(rsa)) | ||
816 | sa := &SockaddrXDP{ | ||
817 | Flags: pp.Flags, | ||
818 | Ifindex: pp.Ifindex, | ||
819 | QueueID: pp.Queue_id, | ||
820 | SharedUmemFD: pp.Shared_umem_fd, | ||
821 | } | ||
822 | return sa, nil | ||
823 | } | ||
824 | return nil, EAFNOSUPPORT | ||
825 | } | ||
826 | |||
827 | func Accept(fd int) (nfd int, sa Sockaddr, err error) { | ||
828 | var rsa RawSockaddrAny | ||
829 | var len _Socklen = SizeofSockaddrAny | ||
830 | nfd, err = accept(fd, &rsa, &len) | ||
831 | if err != nil { | ||
832 | return | ||
833 | } | ||
834 | sa, err = anyToSockaddr(fd, &rsa) | ||
835 | if err != nil { | ||
836 | Close(nfd) | ||
837 | nfd = 0 | ||
838 | } | ||
839 | return | ||
840 | } | ||
841 | |||
842 | func Accept4(fd int, flags int) (nfd int, sa Sockaddr, err error) { | ||
843 | var rsa RawSockaddrAny | ||
844 | var len _Socklen = SizeofSockaddrAny | ||
845 | nfd, err = accept4(fd, &rsa, &len, flags) | ||
846 | if err != nil { | ||
847 | return | ||
848 | } | ||
849 | if len > SizeofSockaddrAny { | ||
850 | panic("RawSockaddrAny too small") | ||
851 | } | ||
852 | sa, err = anyToSockaddr(fd, &rsa) | ||
853 | if err != nil { | ||
854 | Close(nfd) | ||
855 | nfd = 0 | ||
856 | } | ||
857 | return | ||
858 | } | ||
859 | |||
860 | func Getsockname(fd int) (sa Sockaddr, err error) { | ||
861 | var rsa RawSockaddrAny | ||
862 | var len _Socklen = SizeofSockaddrAny | ||
863 | if err = getsockname(fd, &rsa, &len); err != nil { | ||
864 | return | ||
865 | } | ||
866 | return anyToSockaddr(fd, &rsa) | ||
867 | } | ||
868 | |||
869 | func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) { | ||
870 | var value IPMreqn | ||
871 | vallen := _Socklen(SizeofIPMreqn) | ||
872 | err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) | ||
873 | return &value, err | ||
874 | } | ||
875 | |||
876 | func GetsockoptUcred(fd, level, opt int) (*Ucred, error) { | ||
877 | var value Ucred | ||
878 | vallen := _Socklen(SizeofUcred) | ||
879 | err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) | ||
880 | return &value, err | ||
881 | } | ||
882 | |||
883 | func GetsockoptTCPInfo(fd, level, opt int) (*TCPInfo, error) { | ||
884 | var value TCPInfo | ||
885 | vallen := _Socklen(SizeofTCPInfo) | ||
886 | err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen) | ||
887 | return &value, err | ||
888 | } | ||
889 | |||
890 | // GetsockoptString returns the string value of the socket option opt for the | ||
891 | // socket associated with fd at the given socket level. | ||
892 | func GetsockoptString(fd, level, opt int) (string, error) { | ||
893 | buf := make([]byte, 256) | ||
894 | vallen := _Socklen(len(buf)) | ||
895 | err := getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen) | ||
896 | if err != nil { | ||
897 | if err == ERANGE { | ||
898 | buf = make([]byte, vallen) | ||
899 | err = getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen) | ||
900 | } | ||
901 | if err != nil { | ||
902 | return "", err | ||
903 | } | ||
904 | } | ||
905 | return string(buf[:vallen-1]), nil | ||
906 | } | ||
907 | |||
908 | func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) { | ||
909 | return setsockopt(fd, level, opt, unsafe.Pointer(mreq), unsafe.Sizeof(*mreq)) | ||
910 | } | ||
911 | |||
912 | // Keyctl Commands (http://man7.org/linux/man-pages/man2/keyctl.2.html) | ||
913 | |||
914 | // KeyctlInt calls keyctl commands in which each argument is an int. | ||
915 | // These commands are KEYCTL_REVOKE, KEYCTL_CHOWN, KEYCTL_CLEAR, KEYCTL_LINK, | ||
916 | // KEYCTL_UNLINK, KEYCTL_NEGATE, KEYCTL_SET_REQKEY_KEYRING, KEYCTL_SET_TIMEOUT, | ||
917 | // KEYCTL_ASSUME_AUTHORITY, KEYCTL_SESSION_TO_PARENT, KEYCTL_REJECT, | ||
918 | // KEYCTL_INVALIDATE, and KEYCTL_GET_PERSISTENT. | ||
919 | //sys KeyctlInt(cmd int, arg2 int, arg3 int, arg4 int, arg5 int) (ret int, err error) = SYS_KEYCTL | ||
920 | |||
921 | // KeyctlBuffer calls keyctl commands in which the third and fourth | ||
922 | // arguments are a buffer and its length, respectively. | ||
923 | // These commands are KEYCTL_UPDATE, KEYCTL_READ, and KEYCTL_INSTANTIATE. | ||
924 | //sys KeyctlBuffer(cmd int, arg2 int, buf []byte, arg5 int) (ret int, err error) = SYS_KEYCTL | ||
925 | |||
926 | // KeyctlString calls keyctl commands which return a string. | ||
927 | // These commands are KEYCTL_DESCRIBE and KEYCTL_GET_SECURITY. | ||
928 | func KeyctlString(cmd int, id int) (string, error) { | ||
929 | // We must loop as the string data may change in between the syscalls. | ||
930 | // We could allocate a large buffer here to reduce the chance that the | ||
931 | // syscall needs to be called twice; however, this is unnecessary as | ||
932 | // the performance loss is negligible. | ||
933 | var buffer []byte | ||
934 | for { | ||
935 | // Try to fill the buffer with data | ||
936 | length, err := KeyctlBuffer(cmd, id, buffer, 0) | ||
937 | if err != nil { | ||
938 | return "", err | ||
939 | } | ||
940 | |||
941 | // Check if the data was written | ||
942 | if length <= len(buffer) { | ||
943 | // Exclude the null terminator | ||
944 | return string(buffer[:length-1]), nil | ||
945 | } | ||
946 | |||
947 | // Make a bigger buffer if needed | ||
948 | buffer = make([]byte, length) | ||
949 | } | ||
950 | } | ||
951 | |||
952 | // Keyctl commands with special signatures. | ||
953 | |||
954 | // KeyctlGetKeyringID implements the KEYCTL_GET_KEYRING_ID command. | ||
955 | // See the full documentation at: | ||
956 | // http://man7.org/linux/man-pages/man3/keyctl_get_keyring_ID.3.html | ||
957 | func KeyctlGetKeyringID(id int, create bool) (ringid int, err error) { | ||
958 | createInt := 0 | ||
959 | if create { | ||
960 | createInt = 1 | ||
961 | } | ||
962 | return KeyctlInt(KEYCTL_GET_KEYRING_ID, id, createInt, 0, 0) | ||
963 | } | ||
964 | |||
965 | // KeyctlSetperm implements the KEYCTL_SETPERM command. The perm value is the | ||
966 | // key handle permission mask as described in the "keyctl setperm" section of | ||
967 | // http://man7.org/linux/man-pages/man1/keyctl.1.html. | ||
968 | // See the full documentation at: | ||
969 | // http://man7.org/linux/man-pages/man3/keyctl_setperm.3.html | ||
970 | func KeyctlSetperm(id int, perm uint32) error { | ||
971 | _, err := KeyctlInt(KEYCTL_SETPERM, id, int(perm), 0, 0) | ||
972 | return err | ||
973 | } | ||
974 | |||
975 | //sys keyctlJoin(cmd int, arg2 string) (ret int, err error) = SYS_KEYCTL | ||
976 | |||
977 | // KeyctlJoinSessionKeyring implements the KEYCTL_JOIN_SESSION_KEYRING command. | ||
978 | // See the full documentation at: | ||
979 | // http://man7.org/linux/man-pages/man3/keyctl_join_session_keyring.3.html | ||
980 | func KeyctlJoinSessionKeyring(name string) (ringid int, err error) { | ||
981 | return keyctlJoin(KEYCTL_JOIN_SESSION_KEYRING, name) | ||
982 | } | ||
983 | |||
984 | //sys keyctlSearch(cmd int, arg2 int, arg3 string, arg4 string, arg5 int) (ret int, err error) = SYS_KEYCTL | ||
985 | |||
986 | // KeyctlSearch implements the KEYCTL_SEARCH command. | ||
987 | // See the full documentation at: | ||
988 | // http://man7.org/linux/man-pages/man3/keyctl_search.3.html | ||
989 | func KeyctlSearch(ringid int, keyType, description string, destRingid int) (id int, err error) { | ||
990 | return keyctlSearch(KEYCTL_SEARCH, ringid, keyType, description, destRingid) | ||
991 | } | ||
992 | |||
993 | //sys keyctlIOV(cmd int, arg2 int, payload []Iovec, arg5 int) (err error) = SYS_KEYCTL | ||
994 | |||
995 | // KeyctlInstantiateIOV implements the KEYCTL_INSTANTIATE_IOV command. This | ||
996 | // command is similar to KEYCTL_INSTANTIATE, except that the payload is a slice | ||
997 | // of Iovec (each of which represents a buffer) instead of a single buffer. | ||
998 | // See the full documentation at: | ||
999 | // http://man7.org/linux/man-pages/man3/keyctl_instantiate_iov.3.html | ||
1000 | func KeyctlInstantiateIOV(id int, payload []Iovec, ringid int) error { | ||
1001 | return keyctlIOV(KEYCTL_INSTANTIATE_IOV, id, payload, ringid) | ||
1002 | } | ||
1003 | |||
1004 | //sys keyctlDH(cmd int, arg2 *KeyctlDHParams, buf []byte) (ret int, err error) = SYS_KEYCTL | ||
1005 | |||
1006 | // KeyctlDHCompute implements the KEYCTL_DH_COMPUTE command. This command | ||
1007 | // computes a Diffie-Hellman shared secret based on the provide params. The | ||
1008 | // secret is written to the provided buffer and the returned size is the number | ||
1009 | // of bytes written (returning an error if there is insufficient space in the | ||
1010 | // buffer). If a nil buffer is passed in, this function returns the minimum | ||
1011 | // buffer length needed to store the appropriate data. Note that this differs | ||
1012 | // from KEYCTL_READ's behavior which always returns the requested payload size. | ||
1013 | // See the full documentation at: | ||
1014 | // http://man7.org/linux/man-pages/man3/keyctl_dh_compute.3.html | ||
1015 | func KeyctlDHCompute(params *KeyctlDHParams, buffer []byte) (size int, err error) { | ||
1016 | return keyctlDH(KEYCTL_DH_COMPUTE, params, buffer) | ||
1017 | } | ||
1018 | |||
1019 | func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) { | ||
1020 | var msg Msghdr | ||
1021 | var rsa RawSockaddrAny | ||
1022 | msg.Name = (*byte)(unsafe.Pointer(&rsa)) | ||
1023 | msg.Namelen = uint32(SizeofSockaddrAny) | ||
1024 | var iov Iovec | ||
1025 | if len(p) > 0 { | ||
1026 | iov.Base = &p[0] | ||
1027 | iov.SetLen(len(p)) | ||
1028 | } | ||
1029 | var dummy byte | ||
1030 | if len(oob) > 0 { | ||
1031 | if len(p) == 0 { | ||
1032 | var sockType int | ||
1033 | sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE) | ||
1034 | if err != nil { | ||
1035 | return | ||
1036 | } | ||
1037 | // receive at least one normal byte | ||
1038 | if sockType != SOCK_DGRAM { | ||
1039 | iov.Base = &dummy | ||
1040 | iov.SetLen(1) | ||
1041 | } | ||
1042 | } | ||
1043 | msg.Control = &oob[0] | ||
1044 | msg.SetControllen(len(oob)) | ||
1045 | } | ||
1046 | msg.Iov = &iov | ||
1047 | msg.Iovlen = 1 | ||
1048 | if n, err = recvmsg(fd, &msg, flags); err != nil { | ||
1049 | return | ||
1050 | } | ||
1051 | oobn = int(msg.Controllen) | ||
1052 | recvflags = int(msg.Flags) | ||
1053 | // source address is only specified if the socket is unconnected | ||
1054 | if rsa.Addr.Family != AF_UNSPEC { | ||
1055 | from, err = anyToSockaddr(fd, &rsa) | ||
1056 | } | ||
1057 | return | ||
1058 | } | ||
1059 | |||
1060 | func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) { | ||
1061 | _, err = SendmsgN(fd, p, oob, to, flags) | ||
1062 | return | ||
1063 | } | ||
1064 | |||
1065 | func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) { | ||
1066 | var ptr unsafe.Pointer | ||
1067 | var salen _Socklen | ||
1068 | if to != nil { | ||
1069 | var err error | ||
1070 | ptr, salen, err = to.sockaddr() | ||
1071 | if err != nil { | ||
1072 | return 0, err | ||
1073 | } | ||
1074 | } | ||
1075 | var msg Msghdr | ||
1076 | msg.Name = (*byte)(ptr) | ||
1077 | msg.Namelen = uint32(salen) | ||
1078 | var iov Iovec | ||
1079 | if len(p) > 0 { | ||
1080 | iov.Base = &p[0] | ||
1081 | iov.SetLen(len(p)) | ||
1082 | } | ||
1083 | var dummy byte | ||
1084 | if len(oob) > 0 { | ||
1085 | if len(p) == 0 { | ||
1086 | var sockType int | ||
1087 | sockType, err = GetsockoptInt(fd, SOL_SOCKET, SO_TYPE) | ||
1088 | if err != nil { | ||
1089 | return 0, err | ||
1090 | } | ||
1091 | // send at least one normal byte | ||
1092 | if sockType != SOCK_DGRAM { | ||
1093 | iov.Base = &dummy | ||
1094 | iov.SetLen(1) | ||
1095 | } | ||
1096 | } | ||
1097 | msg.Control = &oob[0] | ||
1098 | msg.SetControllen(len(oob)) | ||
1099 | } | ||
1100 | msg.Iov = &iov | ||
1101 | msg.Iovlen = 1 | ||
1102 | if n, err = sendmsg(fd, &msg, flags); err != nil { | ||
1103 | return 0, err | ||
1104 | } | ||
1105 | if len(oob) > 0 && len(p) == 0 { | ||
1106 | n = 0 | ||
1107 | } | ||
1108 | return n, nil | ||
1109 | } | ||
1110 | |||
1111 | // BindToDevice binds the socket associated with fd to device. | ||
1112 | func BindToDevice(fd int, device string) (err error) { | ||
1113 | return SetsockoptString(fd, SOL_SOCKET, SO_BINDTODEVICE, device) | ||
1114 | } | ||
1115 | |||
1116 | //sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) | ||
1117 | |||
1118 | func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, err error) { | ||
1119 | // The peek requests are machine-size oriented, so we wrap it | ||
1120 | // to retrieve arbitrary-length data. | ||
1121 | |||
1122 | // The ptrace syscall differs from glibc's ptrace. | ||
1123 | // Peeks returns the word in *data, not as the return value. | ||
1124 | |||
1125 | var buf [SizeofPtr]byte | ||
1126 | |||
1127 | // Leading edge. PEEKTEXT/PEEKDATA don't require aligned | ||
1128 | // access (PEEKUSER warns that it might), but if we don't | ||
1129 | // align our reads, we might straddle an unmapped page | ||
1130 | // boundary and not get the bytes leading up to the page | ||
1131 | // boundary. | ||
1132 | n := 0 | ||
1133 | if addr%SizeofPtr != 0 { | ||
1134 | err = ptrace(req, pid, addr-addr%SizeofPtr, uintptr(unsafe.Pointer(&buf[0]))) | ||
1135 | if err != nil { | ||
1136 | return 0, err | ||
1137 | } | ||
1138 | n += copy(out, buf[addr%SizeofPtr:]) | ||
1139 | out = out[n:] | ||
1140 | } | ||
1141 | |||
1142 | // Remainder. | ||
1143 | for len(out) > 0 { | ||
1144 | // We use an internal buffer to guarantee alignment. | ||
1145 | // It's not documented if this is necessary, but we're paranoid. | ||
1146 | err = ptrace(req, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0]))) | ||
1147 | if err != nil { | ||
1148 | return n, err | ||
1149 | } | ||
1150 | copied := copy(out, buf[0:]) | ||
1151 | n += copied | ||
1152 | out = out[copied:] | ||
1153 | } | ||
1154 | |||
1155 | return n, nil | ||
1156 | } | ||
1157 | |||
1158 | func PtracePeekText(pid int, addr uintptr, out []byte) (count int, err error) { | ||
1159 | return ptracePeek(PTRACE_PEEKTEXT, pid, addr, out) | ||
1160 | } | ||
1161 | |||
1162 | func PtracePeekData(pid int, addr uintptr, out []byte) (count int, err error) { | ||
1163 | return ptracePeek(PTRACE_PEEKDATA, pid, addr, out) | ||
1164 | } | ||
1165 | |||
1166 | func PtracePeekUser(pid int, addr uintptr, out []byte) (count int, err error) { | ||
1167 | return ptracePeek(PTRACE_PEEKUSR, pid, addr, out) | ||
1168 | } | ||
1169 | |||
1170 | func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (count int, err error) { | ||
1171 | // As for ptracePeek, we need to align our accesses to deal | ||
1172 | // with the possibility of straddling an invalid page. | ||
1173 | |||
1174 | // Leading edge. | ||
1175 | n := 0 | ||
1176 | if addr%SizeofPtr != 0 { | ||
1177 | var buf [SizeofPtr]byte | ||
1178 | err = ptrace(peekReq, pid, addr-addr%SizeofPtr, uintptr(unsafe.Pointer(&buf[0]))) | ||
1179 | if err != nil { | ||
1180 | return 0, err | ||
1181 | } | ||
1182 | n += copy(buf[addr%SizeofPtr:], data) | ||
1183 | word := *((*uintptr)(unsafe.Pointer(&buf[0]))) | ||
1184 | err = ptrace(pokeReq, pid, addr-addr%SizeofPtr, word) | ||
1185 | if err != nil { | ||
1186 | return 0, err | ||
1187 | } | ||
1188 | data = data[n:] | ||
1189 | } | ||
1190 | |||
1191 | // Interior. | ||
1192 | for len(data) > SizeofPtr { | ||
1193 | word := *((*uintptr)(unsafe.Pointer(&data[0]))) | ||
1194 | err = ptrace(pokeReq, pid, addr+uintptr(n), word) | ||
1195 | if err != nil { | ||
1196 | return n, err | ||
1197 | } | ||
1198 | n += SizeofPtr | ||
1199 | data = data[SizeofPtr:] | ||
1200 | } | ||
1201 | |||
1202 | // Trailing edge. | ||
1203 | if len(data) > 0 { | ||
1204 | var buf [SizeofPtr]byte | ||
1205 | err = ptrace(peekReq, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0]))) | ||
1206 | if err != nil { | ||
1207 | return n, err | ||
1208 | } | ||
1209 | copy(buf[0:], data) | ||
1210 | word := *((*uintptr)(unsafe.Pointer(&buf[0]))) | ||
1211 | err = ptrace(pokeReq, pid, addr+uintptr(n), word) | ||
1212 | if err != nil { | ||
1213 | return n, err | ||
1214 | } | ||
1215 | n += len(data) | ||
1216 | } | ||
1217 | |||
1218 | return n, nil | ||
1219 | } | ||
1220 | |||
1221 | func PtracePokeText(pid int, addr uintptr, data []byte) (count int, err error) { | ||
1222 | return ptracePoke(PTRACE_POKETEXT, PTRACE_PEEKTEXT, pid, addr, data) | ||
1223 | } | ||
1224 | |||
1225 | func PtracePokeData(pid int, addr uintptr, data []byte) (count int, err error) { | ||
1226 | return ptracePoke(PTRACE_POKEDATA, PTRACE_PEEKDATA, pid, addr, data) | ||
1227 | } | ||
1228 | |||
1229 | func PtracePokeUser(pid int, addr uintptr, data []byte) (count int, err error) { | ||
1230 | return ptracePoke(PTRACE_POKEUSR, PTRACE_PEEKUSR, pid, addr, data) | ||
1231 | } | ||
1232 | |||
1233 | func PtraceGetRegs(pid int, regsout *PtraceRegs) (err error) { | ||
1234 | return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout))) | ||
1235 | } | ||
1236 | |||
1237 | func PtraceSetRegs(pid int, regs *PtraceRegs) (err error) { | ||
1238 | return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs))) | ||
1239 | } | ||
1240 | |||
1241 | func PtraceSetOptions(pid int, options int) (err error) { | ||
1242 | return ptrace(PTRACE_SETOPTIONS, pid, 0, uintptr(options)) | ||
1243 | } | ||
1244 | |||
1245 | func PtraceGetEventMsg(pid int) (msg uint, err error) { | ||
1246 | var data _C_long | ||
1247 | err = ptrace(PTRACE_GETEVENTMSG, pid, 0, uintptr(unsafe.Pointer(&data))) | ||
1248 | msg = uint(data) | ||
1249 | return | ||
1250 | } | ||
1251 | |||
1252 | func PtraceCont(pid int, signal int) (err error) { | ||
1253 | return ptrace(PTRACE_CONT, pid, 0, uintptr(signal)) | ||
1254 | } | ||
1255 | |||
1256 | func PtraceSyscall(pid int, signal int) (err error) { | ||
1257 | return ptrace(PTRACE_SYSCALL, pid, 0, uintptr(signal)) | ||
1258 | } | ||
1259 | |||
1260 | func PtraceSingleStep(pid int) (err error) { return ptrace(PTRACE_SINGLESTEP, pid, 0, 0) } | ||
1261 | |||
1262 | func PtraceAttach(pid int) (err error) { return ptrace(PTRACE_ATTACH, pid, 0, 0) } | ||
1263 | |||
1264 | func PtraceDetach(pid int) (err error) { return ptrace(PTRACE_DETACH, pid, 0, 0) } | ||
1265 | |||
1266 | //sys reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) | ||
1267 | |||
1268 | func Reboot(cmd int) (err error) { | ||
1269 | return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, "") | ||
1270 | } | ||
1271 | |||
1272 | func ReadDirent(fd int, buf []byte) (n int, err error) { | ||
1273 | return Getdents(fd, buf) | ||
1274 | } | ||
1275 | |||
1276 | //sys mount(source string, target string, fstype string, flags uintptr, data *byte) (err error) | ||
1277 | |||
1278 | func Mount(source string, target string, fstype string, flags uintptr, data string) (err error) { | ||
1279 | // Certain file systems get rather angry and EINVAL if you give | ||
1280 | // them an empty string of data, rather than NULL. | ||
1281 | if data == "" { | ||
1282 | return mount(source, target, fstype, flags, nil) | ||
1283 | } | ||
1284 | datap, err := BytePtrFromString(data) | ||
1285 | if err != nil { | ||
1286 | return err | ||
1287 | } | ||
1288 | return mount(source, target, fstype, flags, datap) | ||
1289 | } | ||
1290 | |||
1291 | // Sendto | ||
1292 | // Recvfrom | ||
1293 | // Socketpair | ||
1294 | |||
1295 | /* | ||
1296 | * Direct access | ||
1297 | */ | ||
1298 | //sys Acct(path string) (err error) | ||
1299 | //sys AddKey(keyType string, description string, payload []byte, ringid int) (id int, err error) | ||
1300 | //sys Adjtimex(buf *Timex) (state int, err error) | ||
1301 | //sys Chdir(path string) (err error) | ||
1302 | //sys Chroot(path string) (err error) | ||
1303 | //sys ClockGetres(clockid int32, res *Timespec) (err error) | ||
1304 | //sys ClockGettime(clockid int32, time *Timespec) (err error) | ||
1305 | //sys Close(fd int) (err error) | ||
1306 | //sys CopyFileRange(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int, err error) | ||
1307 | //sys DeleteModule(name string, flags int) (err error) | ||
1308 | //sys Dup(oldfd int) (fd int, err error) | ||
1309 | //sys Dup3(oldfd int, newfd int, flags int) (err error) | ||
1310 | //sysnb EpollCreate1(flag int) (fd int, err error) | ||
1311 | //sysnb EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) | ||
1312 | //sys Eventfd(initval uint, flags int) (fd int, err error) = SYS_EVENTFD2 | ||
1313 | //sys Exit(code int) = SYS_EXIT_GROUP | ||
1314 | //sys Fallocate(fd int, mode uint32, off int64, len int64) (err error) | ||
1315 | //sys Fchdir(fd int) (err error) | ||
1316 | //sys Fchmod(fd int, mode uint32) (err error) | ||
1317 | //sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) | ||
1318 | //sys fcntl(fd int, cmd int, arg int) (val int, err error) | ||
1319 | //sys Fdatasync(fd int) (err error) | ||
1320 | //sys Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) | ||
1321 | //sys FinitModule(fd int, params string, flags int) (err error) | ||
1322 | //sys Flistxattr(fd int, dest []byte) (sz int, err error) | ||
1323 | //sys Flock(fd int, how int) (err error) | ||
1324 | //sys Fremovexattr(fd int, attr string) (err error) | ||
1325 | //sys Fsetxattr(fd int, attr string, dest []byte, flags int) (err error) | ||
1326 | //sys Fsync(fd int) (err error) | ||
1327 | //sys Getdents(fd int, buf []byte) (n int, err error) = SYS_GETDENTS64 | ||
1328 | //sysnb Getpgid(pid int) (pgid int, err error) | ||
1329 | |||
1330 | func Getpgrp() (pid int) { | ||
1331 | pid, _ = Getpgid(0) | ||
1332 | return | ||
1333 | } | ||
1334 | |||
1335 | //sysnb Getpid() (pid int) | ||
1336 | //sysnb Getppid() (ppid int) | ||
1337 | //sys Getpriority(which int, who int) (prio int, err error) | ||
1338 | //sys Getrandom(buf []byte, flags int) (n int, err error) | ||
1339 | //sysnb Getrusage(who int, rusage *Rusage) (err error) | ||
1340 | //sysnb Getsid(pid int) (sid int, err error) | ||
1341 | //sysnb Gettid() (tid int) | ||
1342 | //sys Getxattr(path string, attr string, dest []byte) (sz int, err error) | ||
1343 | //sys InitModule(moduleImage []byte, params string) (err error) | ||
1344 | //sys InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) | ||
1345 | //sysnb InotifyInit1(flags int) (fd int, err error) | ||
1346 | //sysnb InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) | ||
1347 | //sysnb Kill(pid int, sig syscall.Signal) (err error) | ||
1348 | //sys Klogctl(typ int, buf []byte) (n int, err error) = SYS_SYSLOG | ||
1349 | //sys Lgetxattr(path string, attr string, dest []byte) (sz int, err error) | ||
1350 | //sys Listxattr(path string, dest []byte) (sz int, err error) | ||
1351 | //sys Llistxattr(path string, dest []byte) (sz int, err error) | ||
1352 | //sys Lremovexattr(path string, attr string) (err error) | ||
1353 | //sys Lsetxattr(path string, attr string, data []byte, flags int) (err error) | ||
1354 | //sys MemfdCreate(name string, flags int) (fd int, err error) | ||
1355 | //sys Mkdirat(dirfd int, path string, mode uint32) (err error) | ||
1356 | //sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error) | ||
1357 | //sys Nanosleep(time *Timespec, leftover *Timespec) (err error) | ||
1358 | //sys PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int) (fd int, err error) | ||
1359 | //sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT | ||
1360 | //sysnb prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) = SYS_PRLIMIT64 | ||
1361 | //sys Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) | ||
1362 | //sys Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) = SYS_PSELECT6 | ||
1363 | //sys read(fd int, p []byte) (n int, err error) | ||
1364 | //sys Removexattr(path string, attr string) (err error) | ||
1365 | //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) | ||
1366 | //sys Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) | ||
1367 | //sys RequestKey(keyType string, description string, callback string, destRingid int) (id int, err error) | ||
1368 | //sys Setdomainname(p []byte) (err error) | ||
1369 | //sys Sethostname(p []byte) (err error) | ||
1370 | //sysnb Setpgid(pid int, pgid int) (err error) | ||
1371 | //sysnb Setsid() (pid int, err error) | ||
1372 | //sysnb Settimeofday(tv *Timeval) (err error) | ||
1373 | //sys Setns(fd int, nstype int) (err error) | ||
1374 | |||
1375 | // issue 1435. | ||
1376 | // On linux Setuid and Setgid only affects the current thread, not the process. | ||
1377 | // This does not match what most callers expect so we must return an error | ||
1378 | // here rather than letting the caller think that the call succeeded. | ||
1379 | |||
1380 | func Setuid(uid int) (err error) { | ||
1381 | return EOPNOTSUPP | ||
1382 | } | ||
1383 | |||
1384 | func Setgid(uid int) (err error) { | ||
1385 | return EOPNOTSUPP | ||
1386 | } | ||
1387 | |||
1388 | //sys Setpriority(which int, who int, prio int) (err error) | ||
1389 | //sys Setxattr(path string, attr string, data []byte, flags int) (err error) | ||
1390 | //sys Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) | ||
1391 | //sys Sync() | ||
1392 | //sys Syncfs(fd int) (err error) | ||
1393 | //sysnb Sysinfo(info *Sysinfo_t) (err error) | ||
1394 | //sys Tee(rfd int, wfd int, len int, flags int) (n int64, err error) | ||
1395 | //sysnb Tgkill(tgid int, tid int, sig syscall.Signal) (err error) | ||
1396 | //sysnb Times(tms *Tms) (ticks uintptr, err error) | ||
1397 | //sysnb Umask(mask int) (oldmask int) | ||
1398 | //sysnb Uname(buf *Utsname) (err error) | ||
1399 | //sys Unmount(target string, flags int) (err error) = SYS_UMOUNT2 | ||
1400 | //sys Unshare(flags int) (err error) | ||
1401 | //sys write(fd int, p []byte) (n int, err error) | ||
1402 | //sys exitThread(code int) (err error) = SYS_EXIT | ||
1403 | //sys readlen(fd int, p *byte, np int) (n int, err error) = SYS_READ | ||
1404 | //sys writelen(fd int, p *byte, np int) (n int, err error) = SYS_WRITE | ||
1405 | |||
1406 | // mmap varies by architecture; see syscall_linux_*.go. | ||
1407 | //sys munmap(addr uintptr, length uintptr) (err error) | ||
1408 | |||
1409 | var mapper = &mmapper{ | ||
1410 | active: make(map[*byte][]byte), | ||
1411 | mmap: mmap, | ||
1412 | munmap: munmap, | ||
1413 | } | ||
1414 | |||
1415 | func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) { | ||
1416 | return mapper.Mmap(fd, offset, length, prot, flags) | ||
1417 | } | ||
1418 | |||
1419 | func Munmap(b []byte) (err error) { | ||
1420 | return mapper.Munmap(b) | ||
1421 | } | ||
1422 | |||
1423 | //sys Madvise(b []byte, advice int) (err error) | ||
1424 | //sys Mprotect(b []byte, prot int) (err error) | ||
1425 | //sys Mlock(b []byte) (err error) | ||
1426 | //sys Mlockall(flags int) (err error) | ||
1427 | //sys Msync(b []byte, flags int) (err error) | ||
1428 | //sys Munlock(b []byte) (err error) | ||
1429 | //sys Munlockall() (err error) | ||
1430 | |||
1431 | // Vmsplice splices user pages from a slice of Iovecs into a pipe specified by fd, | ||
1432 | // using the specified flags. | ||
1433 | func Vmsplice(fd int, iovs []Iovec, flags int) (int, error) { | ||
1434 | n, _, errno := Syscall6( | ||
1435 | SYS_VMSPLICE, | ||
1436 | uintptr(fd), | ||
1437 | uintptr(unsafe.Pointer(&iovs[0])), | ||
1438 | uintptr(len(iovs)), | ||
1439 | uintptr(flags), | ||
1440 | 0, | ||
1441 | 0, | ||
1442 | ) | ||
1443 | if errno != 0 { | ||
1444 | return 0, syscall.Errno(errno) | ||
1445 | } | ||
1446 | |||
1447 | return int(n), nil | ||
1448 | } | ||
1449 | |||
1450 | //sys faccessat(dirfd int, path string, mode uint32) (err error) | ||
1451 | |||
1452 | func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { | ||
1453 | if flags & ^(AT_SYMLINK_NOFOLLOW|AT_EACCESS) != 0 { | ||
1454 | return EINVAL | ||
1455 | } | ||
1456 | |||
1457 | // The Linux kernel faccessat system call does not take any flags. | ||
1458 | // The glibc faccessat implements the flags itself; see | ||
1459 | // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/faccessat.c;hb=HEAD | ||
1460 | // Because people naturally expect syscall.Faccessat to act | ||
1461 | // like C faccessat, we do the same. | ||
1462 | |||
1463 | if flags == 0 { | ||
1464 | return faccessat(dirfd, path, mode) | ||
1465 | } | ||
1466 | |||
1467 | var st Stat_t | ||
1468 | if err := Fstatat(dirfd, path, &st, flags&AT_SYMLINK_NOFOLLOW); err != nil { | ||
1469 | return err | ||
1470 | } | ||
1471 | |||
1472 | mode &= 7 | ||
1473 | if mode == 0 { | ||
1474 | return nil | ||
1475 | } | ||
1476 | |||
1477 | var uid int | ||
1478 | if flags&AT_EACCESS != 0 { | ||
1479 | uid = Geteuid() | ||
1480 | } else { | ||
1481 | uid = Getuid() | ||
1482 | } | ||
1483 | |||
1484 | if uid == 0 { | ||
1485 | if mode&1 == 0 { | ||
1486 | // Root can read and write any file. | ||
1487 | return nil | ||
1488 | } | ||
1489 | if st.Mode&0111 != 0 { | ||
1490 | // Root can execute any file that anybody can execute. | ||
1491 | return nil | ||
1492 | } | ||
1493 | return EACCES | ||
1494 | } | ||
1495 | |||
1496 | var fmode uint32 | ||
1497 | if uint32(uid) == st.Uid { | ||
1498 | fmode = (st.Mode >> 6) & 7 | ||
1499 | } else { | ||
1500 | var gid int | ||
1501 | if flags&AT_EACCESS != 0 { | ||
1502 | gid = Getegid() | ||
1503 | } else { | ||
1504 | gid = Getgid() | ||
1505 | } | ||
1506 | |||
1507 | if uint32(gid) == st.Gid { | ||
1508 | fmode = (st.Mode >> 3) & 7 | ||
1509 | } else { | ||
1510 | fmode = st.Mode & 7 | ||
1511 | } | ||
1512 | } | ||
1513 | |||
1514 | if fmode&mode == mode { | ||
1515 | return nil | ||
1516 | } | ||
1517 | |||
1518 | return EACCES | ||
1519 | } | ||
1520 | |||
1521 | /* | ||
1522 | * Unimplemented | ||
1523 | */ | ||
1524 | // AfsSyscall | ||
1525 | // Alarm | ||
1526 | // ArchPrctl | ||
1527 | // Brk | ||
1528 | // Capget | ||
1529 | // Capset | ||
1530 | // ClockNanosleep | ||
1531 | // ClockSettime | ||
1532 | // Clone | ||
1533 | // EpollCtlOld | ||
1534 | // EpollPwait | ||
1535 | // EpollWaitOld | ||
1536 | // Execve | ||
1537 | // Fork | ||
1538 | // Futex | ||
1539 | // GetKernelSyms | ||
1540 | // GetMempolicy | ||
1541 | // GetRobustList | ||
1542 | // GetThreadArea | ||
1543 | // Getitimer | ||
1544 | // Getpmsg | ||
1545 | // IoCancel | ||
1546 | // IoDestroy | ||
1547 | // IoGetevents | ||
1548 | // IoSetup | ||
1549 | // IoSubmit | ||
1550 | // IoprioGet | ||
1551 | // IoprioSet | ||
1552 | // KexecLoad | ||
1553 | // LookupDcookie | ||
1554 | // Mbind | ||
1555 | // MigratePages | ||
1556 | // Mincore | ||
1557 | // ModifyLdt | ||
1558 | // Mount | ||
1559 | // MovePages | ||
1560 | // MqGetsetattr | ||
1561 | // MqNotify | ||
1562 | // MqOpen | ||
1563 | // MqTimedreceive | ||
1564 | // MqTimedsend | ||
1565 | // MqUnlink | ||
1566 | // Mremap | ||
1567 | // Msgctl | ||
1568 | // Msgget | ||
1569 | // Msgrcv | ||
1570 | // Msgsnd | ||
1571 | // Nfsservctl | ||
1572 | // Personality | ||
1573 | // Pselect6 | ||
1574 | // Ptrace | ||
1575 | // Putpmsg | ||
1576 | // Quotactl | ||
1577 | // Readahead | ||
1578 | // Readv | ||
1579 | // RemapFilePages | ||
1580 | // RestartSyscall | ||
1581 | // RtSigaction | ||
1582 | // RtSigpending | ||
1583 | // RtSigprocmask | ||
1584 | // RtSigqueueinfo | ||
1585 | // RtSigreturn | ||
1586 | // RtSigsuspend | ||
1587 | // RtSigtimedwait | ||
1588 | // SchedGetPriorityMax | ||
1589 | // SchedGetPriorityMin | ||
1590 | // SchedGetparam | ||
1591 | // SchedGetscheduler | ||
1592 | // SchedRrGetInterval | ||
1593 | // SchedSetparam | ||
1594 | // SchedYield | ||
1595 | // Security | ||
1596 | // Semctl | ||
1597 | // Semget | ||
1598 | // Semop | ||
1599 | // Semtimedop | ||
1600 | // SetMempolicy | ||
1601 | // SetRobustList | ||
1602 | // SetThreadArea | ||
1603 | // SetTidAddress | ||
1604 | // Shmat | ||
1605 | // Shmctl | ||
1606 | // Shmdt | ||
1607 | // Shmget | ||
1608 | // Sigaltstack | ||
1609 | // Signalfd | ||
1610 | // Swapoff | ||
1611 | // Swapon | ||
1612 | // Sysfs | ||
1613 | // TimerCreate | ||
1614 | // TimerDelete | ||
1615 | // TimerGetoverrun | ||
1616 | // TimerGettime | ||
1617 | // TimerSettime | ||
1618 | // Timerfd | ||
1619 | // Tkill (obsolete) | ||
1620 | // Tuxcall | ||
1621 | // Umount2 | ||
1622 | // Uselib | ||
1623 | // Utimensat | ||
1624 | // Vfork | ||
1625 | // Vhangup | ||
1626 | // Vserver | ||
1627 | // Waitid | ||
1628 | // _Sysctl | ||