aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/golang.org/x/sys/unix/syscall_solaris.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/sys/unix/syscall_solaris.go')
-rw-r--r--vendor/golang.org/x/sys/unix/syscall_solaris.go1104
1 files changed, 1104 insertions, 0 deletions
diff --git a/vendor/golang.org/x/sys/unix/syscall_solaris.go b/vendor/golang.org/x/sys/unix/syscall_solaris.go
new file mode 100644
index 0000000..21974af
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/syscall_solaris.go
@@ -0,0 +1,1104 @@
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// Solaris 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 wrap
10// it in our own nicer implementation, either here or in
11// syscall_solaris.go or syscall_unix.go.
12
13package unix
14
15import (
16 "fmt"
17 "os"
18 "runtime"
19 "sync"
20 "syscall"
21 "unsafe"
22)
23
24// Implemented in runtime/syscall_solaris.go.
25type syscallFunc uintptr
26
27func rawSysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
28func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
29
30// SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets.
31type SockaddrDatalink struct {
32 Family uint16
33 Index uint16
34 Type uint8
35 Nlen uint8
36 Alen uint8
37 Slen uint8
38 Data [244]int8
39 raw RawSockaddrDatalink
40}
41
42func direntIno(buf []byte) (uint64, bool) {
43 return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
44}
45
46func direntReclen(buf []byte) (uint64, bool) {
47 return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
48}
49
50func direntNamlen(buf []byte) (uint64, bool) {
51 reclen, ok := direntReclen(buf)
52 if !ok {
53 return 0, false
54 }
55 return reclen - uint64(unsafe.Offsetof(Dirent{}.Name)), true
56}
57
58//sysnb pipe(p *[2]_C_int) (n int, err error)
59
60func Pipe(p []int) (err error) {
61 if len(p) != 2 {
62 return EINVAL
63 }
64 var pp [2]_C_int
65 n, err := pipe(&pp)
66 if n != 0 {
67 return err
68 }
69 if err == nil {
70 p[0] = int(pp[0])
71 p[1] = int(pp[1])
72 }
73 return nil
74}
75
76//sysnb pipe2(p *[2]_C_int, flags int) (err error)
77
78func Pipe2(p []int, flags int) error {
79 if len(p) != 2 {
80 return EINVAL
81 }
82 var pp [2]_C_int
83 err := pipe2(&pp, flags)
84 if err == nil {
85 p[0] = int(pp[0])
86 p[1] = int(pp[1])
87 }
88 return err
89}
90
91func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
92 if sa.Port < 0 || sa.Port > 0xFFFF {
93 return nil, 0, EINVAL
94 }
95 sa.raw.Family = AF_INET
96 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
97 p[0] = byte(sa.Port >> 8)
98 p[1] = byte(sa.Port)
99 sa.raw.Addr = sa.Addr
100 return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
101}
102
103func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
104 if sa.Port < 0 || sa.Port > 0xFFFF {
105 return nil, 0, EINVAL
106 }
107 sa.raw.Family = AF_INET6
108 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
109 p[0] = byte(sa.Port >> 8)
110 p[1] = byte(sa.Port)
111 sa.raw.Scope_id = sa.ZoneId
112 sa.raw.Addr = sa.Addr
113 return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
114}
115
116func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
117 name := sa.Name
118 n := len(name)
119 if n >= len(sa.raw.Path) {
120 return nil, 0, EINVAL
121 }
122 sa.raw.Family = AF_UNIX
123 for i := 0; i < n; i++ {
124 sa.raw.Path[i] = int8(name[i])
125 }
126 // length is family (uint16), name, NUL.
127 sl := _Socklen(2)
128 if n > 0 {
129 sl += _Socklen(n) + 1
130 }
131 if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) {
132 // Check sl > 3 so we don't change unnamed socket behavior.
133 sa.raw.Path[0] = 0
134 // Don't count trailing NUL for abstract address.
135 sl--
136 }
137
138 return unsafe.Pointer(&sa.raw), sl, nil
139}
140
141//sys getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getsockname
142
143func Getsockname(fd int) (sa Sockaddr, err error) {
144 var rsa RawSockaddrAny
145 var len _Socklen = SizeofSockaddrAny
146 if err = getsockname(fd, &rsa, &len); err != nil {
147 return
148 }
149 return anyToSockaddr(fd, &rsa)
150}
151
152// GetsockoptString returns the string value of the socket option opt for the
153// socket associated with fd at the given socket level.
154func GetsockoptString(fd, level, opt int) (string, error) {
155 buf := make([]byte, 256)
156 vallen := _Socklen(len(buf))
157 err := getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen)
158 if err != nil {
159 return "", err
160 }
161 return ByteSliceToString(buf[:vallen]), nil
162}
163
164const ImplementsGetwd = true
165
166//sys Getcwd(buf []byte) (n int, err error)
167
168func Getwd() (wd string, err error) {
169 var buf [PathMax]byte
170 // Getcwd will return an error if it failed for any reason.
171 _, err = Getcwd(buf[0:])
172 if err != nil {
173 return "", err
174 }
175 n := clen(buf[:])
176 if n < 1 {
177 return "", EINVAL
178 }
179 return string(buf[:n]), nil
180}
181
182/*
183 * Wrapped
184 */
185
186//sysnb getgroups(ngid int, gid *_Gid_t) (n int, err error)
187//sysnb setgroups(ngid int, gid *_Gid_t) (err error)
188
189func Getgroups() (gids []int, err error) {
190 n, err := getgroups(0, nil)
191 // Check for error and sanity check group count. Newer versions of
192 // Solaris allow up to 1024 (NGROUPS_MAX).
193 if n < 0 || n > 1024 {
194 if err != nil {
195 return nil, err
196 }
197 return nil, EINVAL
198 } else if n == 0 {
199 return nil, nil
200 }
201
202 a := make([]_Gid_t, n)
203 n, err = getgroups(n, &a[0])
204 if n == -1 {
205 return nil, err
206 }
207 gids = make([]int, n)
208 for i, v := range a[0:n] {
209 gids[i] = int(v)
210 }
211 return
212}
213
214func Setgroups(gids []int) (err error) {
215 if len(gids) == 0 {
216 return setgroups(0, nil)
217 }
218
219 a := make([]_Gid_t, len(gids))
220 for i, v := range gids {
221 a[i] = _Gid_t(v)
222 }
223 return setgroups(len(a), &a[0])
224}
225
226// ReadDirent reads directory entries from fd and writes them into buf.
227func ReadDirent(fd int, buf []byte) (n int, err error) {
228 // Final argument is (basep *uintptr) and the syscall doesn't take nil.
229 // TODO(rsc): Can we use a single global basep for all calls?
230 return Getdents(fd, buf, new(uintptr))
231}
232
233// Wait status is 7 bits at bottom, either 0 (exited),
234// 0x7F (stopped), or a signal number that caused an exit.
235// The 0x80 bit is whether there was a core dump.
236// An extra number (exit code, signal causing a stop)
237// is in the high bits.
238
239type WaitStatus uint32
240
241const (
242 mask = 0x7F
243 core = 0x80
244 shift = 8
245
246 exited = 0
247 stopped = 0x7F
248)
249
250func (w WaitStatus) Exited() bool { return w&mask == exited }
251
252func (w WaitStatus) ExitStatus() int {
253 if w&mask != exited {
254 return -1
255 }
256 return int(w >> shift)
257}
258
259func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 }
260
261func (w WaitStatus) Signal() syscall.Signal {
262 sig := syscall.Signal(w & mask)
263 if sig == stopped || sig == 0 {
264 return -1
265 }
266 return sig
267}
268
269func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
270
271func (w WaitStatus) Stopped() bool { return w&mask == stopped && syscall.Signal(w>>shift) != SIGSTOP }
272
273func (w WaitStatus) Continued() bool { return w&mask == stopped && syscall.Signal(w>>shift) == SIGSTOP }
274
275func (w WaitStatus) StopSignal() syscall.Signal {
276 if !w.Stopped() {
277 return -1
278 }
279 return syscall.Signal(w>>shift) & 0xFF
280}
281
282func (w WaitStatus) TrapCause() int { return -1 }
283
284//sys wait4(pid int32, statusp *_C_int, options int, rusage *Rusage) (wpid int32, err error)
285
286func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (int, error) {
287 var status _C_int
288 rpid, err := wait4(int32(pid), &status, options, rusage)
289 wpid := int(rpid)
290 if wpid == -1 {
291 return wpid, err
292 }
293 if wstatus != nil {
294 *wstatus = WaitStatus(status)
295 }
296 return wpid, nil
297}
298
299//sys gethostname(buf []byte) (n int, err error)
300
301func Gethostname() (name string, err error) {
302 var buf [MaxHostNameLen]byte
303 n, err := gethostname(buf[:])
304 if n != 0 {
305 return "", err
306 }
307 n = clen(buf[:])
308 if n < 1 {
309 return "", EFAULT
310 }
311 return string(buf[:n]), nil
312}
313
314//sys utimes(path string, times *[2]Timeval) (err error)
315
316func Utimes(path string, tv []Timeval) (err error) {
317 if tv == nil {
318 return utimes(path, nil)
319 }
320 if len(tv) != 2 {
321 return EINVAL
322 }
323 return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
324}
325
326//sys utimensat(fd int, path string, times *[2]Timespec, flag int) (err error)
327
328func UtimesNano(path string, ts []Timespec) error {
329 if ts == nil {
330 return utimensat(AT_FDCWD, path, nil, 0)
331 }
332 if len(ts) != 2 {
333 return EINVAL
334 }
335 return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
336}
337
338func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error {
339 if ts == nil {
340 return utimensat(dirfd, path, nil, flags)
341 }
342 if len(ts) != 2 {
343 return EINVAL
344 }
345 return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags)
346}
347
348//sys fcntl(fd int, cmd int, arg int) (val int, err error)
349
350// FcntlInt performs a fcntl syscall on fd with the provided command and argument.
351func FcntlInt(fd uintptr, cmd, arg int) (int, error) {
352 valptr, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procfcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(arg), 0, 0, 0)
353 var err error
354 if errno != 0 {
355 err = errno
356 }
357 return int(valptr), err
358}
359
360// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command.
361func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
362 _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procfcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(lk)), 0, 0, 0)
363 if e1 != 0 {
364 return e1
365 }
366 return nil
367}
368
369//sys futimesat(fildes int, path *byte, times *[2]Timeval) (err error)
370
371func Futimesat(dirfd int, path string, tv []Timeval) error {
372 pathp, err := BytePtrFromString(path)
373 if err != nil {
374 return err
375 }
376 if tv == nil {
377 return futimesat(dirfd, pathp, nil)
378 }
379 if len(tv) != 2 {
380 return EINVAL
381 }
382 return futimesat(dirfd, pathp, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
383}
384
385// Solaris doesn't have an futimes function because it allows NULL to be
386// specified as the path for futimesat. However, Go doesn't like
387// NULL-style string interfaces, so this simple wrapper is provided.
388func Futimes(fd int, tv []Timeval) error {
389 if tv == nil {
390 return futimesat(fd, nil, nil)
391 }
392 if len(tv) != 2 {
393 return EINVAL
394 }
395 return futimesat(fd, nil, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
396}
397
398func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
399 switch rsa.Addr.Family {
400 case AF_UNIX:
401 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
402 sa := new(SockaddrUnix)
403 // Assume path ends at NUL.
404 // This is not technically the Solaris semantics for
405 // abstract Unix domain sockets -- they are supposed
406 // to be uninterpreted fixed-size binary blobs -- but
407 // everyone uses this convention.
408 n := 0
409 for n < len(pp.Path) && pp.Path[n] != 0 {
410 n++
411 }
412 sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n))
413 return sa, nil
414
415 case AF_INET:
416 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
417 sa := new(SockaddrInet4)
418 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
419 sa.Port = int(p[0])<<8 + int(p[1])
420 sa.Addr = pp.Addr
421 return sa, nil
422
423 case AF_INET6:
424 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
425 sa := new(SockaddrInet6)
426 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
427 sa.Port = int(p[0])<<8 + int(p[1])
428 sa.ZoneId = pp.Scope_id
429 sa.Addr = pp.Addr
430 return sa, nil
431 }
432 return nil, EAFNOSUPPORT
433}
434
435//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) = libsocket.accept
436
437func Accept(fd int) (nfd int, sa Sockaddr, err error) {
438 var rsa RawSockaddrAny
439 var len _Socklen = SizeofSockaddrAny
440 nfd, err = accept(fd, &rsa, &len)
441 if nfd == -1 {
442 return
443 }
444 sa, err = anyToSockaddr(fd, &rsa)
445 if err != nil {
446 Close(nfd)
447 nfd = 0
448 }
449 return
450}
451
452//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_recvmsg
453
454func recvmsgRaw(fd int, iov []Iovec, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) {
455 var msg Msghdr
456 msg.Name = (*byte)(unsafe.Pointer(rsa))
457 msg.Namelen = uint32(SizeofSockaddrAny)
458 var dummy byte
459 if len(oob) > 0 {
460 // receive at least one normal byte
461 if emptyIovecs(iov) {
462 var iova [1]Iovec
463 iova[0].Base = &dummy
464 iova[0].SetLen(1)
465 iov = iova[:]
466 }
467 msg.Accrightslen = int32(len(oob))
468 }
469 if len(iov) > 0 {
470 msg.Iov = &iov[0]
471 msg.SetIovlen(len(iov))
472 }
473 if n, err = recvmsg(fd, &msg, flags); n == -1 {
474 return
475 }
476 oobn = int(msg.Accrightslen)
477 return
478}
479
480//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) = libsocket.__xnet_sendmsg
481
482func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) {
483 var msg Msghdr
484 msg.Name = (*byte)(unsafe.Pointer(ptr))
485 msg.Namelen = uint32(salen)
486 var dummy byte
487 var empty bool
488 if len(oob) > 0 {
489 // send at least one normal byte
490 empty = emptyIovecs(iov)
491 if empty {
492 var iova [1]Iovec
493 iova[0].Base = &dummy
494 iova[0].SetLen(1)
495 iov = iova[:]
496 }
497 msg.Accrightslen = int32(len(oob))
498 }
499 if len(iov) > 0 {
500 msg.Iov = &iov[0]
501 msg.SetIovlen(len(iov))
502 }
503 if n, err = sendmsg(fd, &msg, flags); err != nil {
504 return 0, err
505 }
506 if len(oob) > 0 && empty {
507 n = 0
508 }
509 return n, nil
510}
511
512//sys acct(path *byte) (err error)
513
514func Acct(path string) (err error) {
515 if len(path) == 0 {
516 // Assume caller wants to disable accounting.
517 return acct(nil)
518 }
519
520 pathp, err := BytePtrFromString(path)
521 if err != nil {
522 return err
523 }
524 return acct(pathp)
525}
526
527//sys __makedev(version int, major uint, minor uint) (val uint64)
528
529func Mkdev(major, minor uint32) uint64 {
530 return __makedev(NEWDEV, uint(major), uint(minor))
531}
532
533//sys __major(version int, dev uint64) (val uint)
534
535func Major(dev uint64) uint32 {
536 return uint32(__major(NEWDEV, dev))
537}
538
539//sys __minor(version int, dev uint64) (val uint)
540
541func Minor(dev uint64) uint32 {
542 return uint32(__minor(NEWDEV, dev))
543}
544
545/*
546 * Expose the ioctl function
547 */
548
549//sys ioctlRet(fd int, req int, arg uintptr) (ret int, err error) = libc.ioctl
550//sys ioctlPtrRet(fd int, req int, arg unsafe.Pointer) (ret int, err error) = libc.ioctl
551
552func ioctl(fd int, req int, arg uintptr) (err error) {
553 _, err = ioctlRet(fd, req, arg)
554 return err
555}
556
557func ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) {
558 _, err = ioctlPtrRet(fd, req, arg)
559 return err
560}
561
562func IoctlSetTermio(fd int, req int, value *Termio) error {
563 return ioctlPtr(fd, req, unsafe.Pointer(value))
564}
565
566func IoctlGetTermio(fd int, req int) (*Termio, error) {
567 var value Termio
568 err := ioctlPtr(fd, req, unsafe.Pointer(&value))
569 return &value, err
570}
571
572//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
573
574func Poll(fds []PollFd, timeout int) (n int, err error) {
575 if len(fds) == 0 {
576 return poll(nil, 0, timeout)
577 }
578 return poll(&fds[0], len(fds), timeout)
579}
580
581func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
582 if raceenabled {
583 raceReleaseMerge(unsafe.Pointer(&ioSync))
584 }
585 return sendfile(outfd, infd, offset, count)
586}
587
588/*
589 * Exposed directly
590 */
591//sys Access(path string, mode uint32) (err error)
592//sys Adjtime(delta *Timeval, olddelta *Timeval) (err error)
593//sys Chdir(path string) (err error)
594//sys Chmod(path string, mode uint32) (err error)
595//sys Chown(path string, uid int, gid int) (err error)
596//sys Chroot(path string) (err error)
597//sys ClockGettime(clockid int32, time *Timespec) (err error)
598//sys Close(fd int) (err error)
599//sys Creat(path string, mode uint32) (fd int, err error)
600//sys Dup(fd int) (nfd int, err error)
601//sys Dup2(oldfd int, newfd int) (err error)
602//sys Exit(code int)
603//sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error)
604//sys Fchdir(fd int) (err error)
605//sys Fchmod(fd int, mode uint32) (err error)
606//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
607//sys Fchown(fd int, uid int, gid int) (err error)
608//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
609//sys Fdatasync(fd int) (err error)
610//sys Flock(fd int, how int) (err error)
611//sys Fpathconf(fd int, name int) (val int, err error)
612//sys Fstat(fd int, stat *Stat_t) (err error)
613//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
614//sys Fstatvfs(fd int, vfsstat *Statvfs_t) (err error)
615//sys Getdents(fd int, buf []byte, basep *uintptr) (n int, err error)
616//sysnb Getgid() (gid int)
617//sysnb Getpid() (pid int)
618//sysnb Getpgid(pid int) (pgid int, err error)
619//sysnb Getpgrp() (pgid int, err error)
620//sys Geteuid() (euid int)
621//sys Getegid() (egid int)
622//sys Getppid() (ppid int)
623//sys Getpriority(which int, who int) (n int, err error)
624//sysnb Getrlimit(which int, lim *Rlimit) (err error)
625//sysnb Getrusage(who int, rusage *Rusage) (err error)
626//sysnb Getsid(pid int) (sid int, err error)
627//sysnb Gettimeofday(tv *Timeval) (err error)
628//sysnb Getuid() (uid int)
629//sys Kill(pid int, signum syscall.Signal) (err error)
630//sys Lchown(path string, uid int, gid int) (err error)
631//sys Link(path string, link string) (err error)
632//sys Listen(s int, backlog int) (err error) = libsocket.__xnet_llisten
633//sys Lstat(path string, stat *Stat_t) (err error)
634//sys Madvise(b []byte, advice int) (err error)
635//sys Mkdir(path string, mode uint32) (err error)
636//sys Mkdirat(dirfd int, path string, mode uint32) (err error)
637//sys Mkfifo(path string, mode uint32) (err error)
638//sys Mkfifoat(dirfd int, path string, mode uint32) (err error)
639//sys Mknod(path string, mode uint32, dev int) (err error)
640//sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error)
641//sys Mlock(b []byte) (err error)
642//sys Mlockall(flags int) (err error)
643//sys Mprotect(b []byte, prot int) (err error)
644//sys Msync(b []byte, flags int) (err error)
645//sys Munlock(b []byte) (err error)
646//sys Munlockall() (err error)
647//sys Nanosleep(time *Timespec, leftover *Timespec) (err error)
648//sys Open(path string, mode int, perm uint32) (fd int, err error)
649//sys Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
650//sys Pathconf(path string, name int) (val int, err error)
651//sys Pause() (err error)
652//sys pread(fd int, p []byte, offset int64) (n int, err error)
653//sys pwrite(fd int, p []byte, offset int64) (n int, err error)
654//sys read(fd int, p []byte) (n int, err error)
655//sys Readlink(path string, buf []byte) (n int, err error)
656//sys Rename(from string, to string) (err error)
657//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
658//sys Rmdir(path string) (err error)
659//sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek
660//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
661//sysnb Setegid(egid int) (err error)
662//sysnb Seteuid(euid int) (err error)
663//sysnb Setgid(gid int) (err error)
664//sys Sethostname(p []byte) (err error)
665//sysnb Setpgid(pid int, pgid int) (err error)
666//sys Setpriority(which int, who int, prio int) (err error)
667//sysnb Setregid(rgid int, egid int) (err error)
668//sysnb Setreuid(ruid int, euid int) (err error)
669//sysnb Setsid() (pid int, err error)
670//sysnb Setuid(uid int) (err error)
671//sys Shutdown(s int, how int) (err error) = libsocket.shutdown
672//sys Stat(path string, stat *Stat_t) (err error)
673//sys Statvfs(path string, vfsstat *Statvfs_t) (err error)
674//sys Symlink(path string, link string) (err error)
675//sys Sync() (err error)
676//sys Sysconf(which int) (n int64, err error)
677//sysnb Times(tms *Tms) (ticks uintptr, err error)
678//sys Truncate(path string, length int64) (err error)
679//sys Fsync(fd int) (err error)
680//sys Ftruncate(fd int, length int64) (err error)
681//sys Umask(mask int) (oldmask int)
682//sysnb Uname(buf *Utsname) (err error)
683//sys Unmount(target string, flags int) (err error) = libc.umount
684//sys Unlink(path string) (err error)
685//sys Unlinkat(dirfd int, path string, flags int) (err error)
686//sys Ustat(dev int, ubuf *Ustat_t) (err error)
687//sys Utime(path string, buf *Utimbuf) (err error)
688//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_bind
689//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_connect
690//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
691//sys munmap(addr uintptr, length uintptr) (err error)
692//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = libsendfile.sendfile
693//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_sendto
694//sys socket(domain int, typ int, proto int) (fd int, err error) = libsocket.__xnet_socket
695//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) = libsocket.__xnet_socketpair
696//sys write(fd int, p []byte) (n int, err error)
697//sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) = libsocket.__xnet_getsockopt
698//sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getpeername
699//sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) = libsocket.setsockopt
700//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = libsocket.recvfrom
701
702// Event Ports
703
704type fileObjCookie struct {
705 fobj *fileObj
706 cookie interface{}
707}
708
709// EventPort provides a safe abstraction on top of Solaris/illumos Event Ports.
710type EventPort struct {
711 port int
712 mu sync.Mutex
713 fds map[uintptr]*fileObjCookie
714 paths map[string]*fileObjCookie
715 // The user cookie presents an interesting challenge from a memory management perspective.
716 // There are two paths by which we can discover that it is no longer in use:
717 // 1. The user calls port_dissociate before any events fire
718 // 2. An event fires and we return it to the user
719 // The tricky situation is if the event has fired in the kernel but
720 // the user hasn't requested/received it yet.
721 // If the user wants to port_dissociate before the event has been processed,
722 // we should handle things gracefully. To do so, we need to keep an extra
723 // reference to the cookie around until the event is processed
724 // thus the otherwise seemingly extraneous "cookies" map
725 // The key of this map is a pointer to the corresponding fCookie
726 cookies map[*fileObjCookie]struct{}
727}
728
729// PortEvent is an abstraction of the port_event C struct.
730// Compare Source against PORT_SOURCE_FILE or PORT_SOURCE_FD
731// to see if Path or Fd was the event source. The other will be
732// uninitialized.
733type PortEvent struct {
734 Cookie interface{}
735 Events int32
736 Fd uintptr
737 Path string
738 Source uint16
739 fobj *fileObj
740}
741
742// NewEventPort creates a new EventPort including the
743// underlying call to port_create(3c).
744func NewEventPort() (*EventPort, error) {
745 port, err := port_create()
746 if err != nil {
747 return nil, err
748 }
749 e := &EventPort{
750 port: port,
751 fds: make(map[uintptr]*fileObjCookie),
752 paths: make(map[string]*fileObjCookie),
753 cookies: make(map[*fileObjCookie]struct{}),
754 }
755 return e, nil
756}
757
758//sys port_create() (n int, err error)
759//sys port_associate(port int, source int, object uintptr, events int, user *byte) (n int, err error)
760//sys port_dissociate(port int, source int, object uintptr) (n int, err error)
761//sys port_get(port int, pe *portEvent, timeout *Timespec) (n int, err error)
762//sys port_getn(port int, pe *portEvent, max uint32, nget *uint32, timeout *Timespec) (n int, err error)
763
764// Close closes the event port.
765func (e *EventPort) Close() error {
766 e.mu.Lock()
767 defer e.mu.Unlock()
768 err := Close(e.port)
769 if err != nil {
770 return err
771 }
772 e.fds = nil
773 e.paths = nil
774 e.cookies = nil
775 return nil
776}
777
778// PathIsWatched checks to see if path is associated with this EventPort.
779func (e *EventPort) PathIsWatched(path string) bool {
780 e.mu.Lock()
781 defer e.mu.Unlock()
782 _, found := e.paths[path]
783 return found
784}
785
786// FdIsWatched checks to see if fd is associated with this EventPort.
787func (e *EventPort) FdIsWatched(fd uintptr) bool {
788 e.mu.Lock()
789 defer e.mu.Unlock()
790 _, found := e.fds[fd]
791 return found
792}
793
794// AssociatePath wraps port_associate(3c) for a filesystem path including
795// creating the necessary file_obj from the provided stat information.
796func (e *EventPort) AssociatePath(path string, stat os.FileInfo, events int, cookie interface{}) error {
797 e.mu.Lock()
798 defer e.mu.Unlock()
799 if _, found := e.paths[path]; found {
800 return fmt.Errorf("%v is already associated with this Event Port", path)
801 }
802 fCookie, err := createFileObjCookie(path, stat, cookie)
803 if err != nil {
804 return err
805 }
806 _, err = port_associate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(fCookie.fobj)), events, (*byte)(unsafe.Pointer(fCookie)))
807 if err != nil {
808 return err
809 }
810 e.paths[path] = fCookie
811 e.cookies[fCookie] = struct{}{}
812 return nil
813}
814
815// DissociatePath wraps port_dissociate(3c) for a filesystem path.
816func (e *EventPort) DissociatePath(path string) error {
817 e.mu.Lock()
818 defer e.mu.Unlock()
819 f, ok := e.paths[path]
820 if !ok {
821 return fmt.Errorf("%v is not associated with this Event Port", path)
822 }
823 _, err := port_dissociate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(f.fobj)))
824 // If the path is no longer associated with this event port (ENOENT)
825 // we should delete it from our map. We can still return ENOENT to the caller.
826 // But we need to save the cookie
827 if err != nil && err != ENOENT {
828 return err
829 }
830 if err == nil {
831 // dissociate was successful, safe to delete the cookie
832 fCookie := e.paths[path]
833 delete(e.cookies, fCookie)
834 }
835 delete(e.paths, path)
836 return err
837}
838
839// AssociateFd wraps calls to port_associate(3c) on file descriptors.
840func (e *EventPort) AssociateFd(fd uintptr, events int, cookie interface{}) error {
841 e.mu.Lock()
842 defer e.mu.Unlock()
843 if _, found := e.fds[fd]; found {
844 return fmt.Errorf("%v is already associated with this Event Port", fd)
845 }
846 fCookie, err := createFileObjCookie("", nil, cookie)
847 if err != nil {
848 return err
849 }
850 _, err = port_associate(e.port, PORT_SOURCE_FD, fd, events, (*byte)(unsafe.Pointer(fCookie)))
851 if err != nil {
852 return err
853 }
854 e.fds[fd] = fCookie
855 e.cookies[fCookie] = struct{}{}
856 return nil
857}
858
859// DissociateFd wraps calls to port_dissociate(3c) on file descriptors.
860func (e *EventPort) DissociateFd(fd uintptr) error {
861 e.mu.Lock()
862 defer e.mu.Unlock()
863 _, ok := e.fds[fd]
864 if !ok {
865 return fmt.Errorf("%v is not associated with this Event Port", fd)
866 }
867 _, err := port_dissociate(e.port, PORT_SOURCE_FD, fd)
868 if err != nil && err != ENOENT {
869 return err
870 }
871 if err == nil {
872 // dissociate was successful, safe to delete the cookie
873 fCookie := e.fds[fd]
874 delete(e.cookies, fCookie)
875 }
876 delete(e.fds, fd)
877 return err
878}
879
880func createFileObjCookie(name string, stat os.FileInfo, cookie interface{}) (*fileObjCookie, error) {
881 fCookie := new(fileObjCookie)
882 fCookie.cookie = cookie
883 if name != "" && stat != nil {
884 fCookie.fobj = new(fileObj)
885 bs, err := ByteSliceFromString(name)
886 if err != nil {
887 return nil, err
888 }
889 fCookie.fobj.Name = (*int8)(unsafe.Pointer(&bs[0]))
890 s := stat.Sys().(*syscall.Stat_t)
891 fCookie.fobj.Atim.Sec = s.Atim.Sec
892 fCookie.fobj.Atim.Nsec = s.Atim.Nsec
893 fCookie.fobj.Mtim.Sec = s.Mtim.Sec
894 fCookie.fobj.Mtim.Nsec = s.Mtim.Nsec
895 fCookie.fobj.Ctim.Sec = s.Ctim.Sec
896 fCookie.fobj.Ctim.Nsec = s.Ctim.Nsec
897 }
898 return fCookie, nil
899}
900
901// GetOne wraps port_get(3c) and returns a single PortEvent.
902func (e *EventPort) GetOne(t *Timespec) (*PortEvent, error) {
903 pe := new(portEvent)
904 _, err := port_get(e.port, pe, t)
905 if err != nil {
906 return nil, err
907 }
908 p := new(PortEvent)
909 e.mu.Lock()
910 defer e.mu.Unlock()
911 err = e.peIntToExt(pe, p)
912 if err != nil {
913 return nil, err
914 }
915 return p, nil
916}
917
918// peIntToExt converts a cgo portEvent struct into the friendlier PortEvent
919// NOTE: Always call this function while holding the e.mu mutex
920func (e *EventPort) peIntToExt(peInt *portEvent, peExt *PortEvent) error {
921 if e.cookies == nil {
922 return fmt.Errorf("this EventPort is already closed")
923 }
924 peExt.Events = peInt.Events
925 peExt.Source = peInt.Source
926 fCookie := (*fileObjCookie)(unsafe.Pointer(peInt.User))
927 _, found := e.cookies[fCookie]
928
929 if !found {
930 panic("unexpected event port address; may be due to kernel bug; see https://go.dev/issue/54254")
931 }
932 peExt.Cookie = fCookie.cookie
933 delete(e.cookies, fCookie)
934
935 switch peInt.Source {
936 case PORT_SOURCE_FD:
937 peExt.Fd = uintptr(peInt.Object)
938 // Only remove the fds entry if it exists and this cookie matches
939 if fobj, ok := e.fds[peExt.Fd]; ok {
940 if fobj == fCookie {
941 delete(e.fds, peExt.Fd)
942 }
943 }
944 case PORT_SOURCE_FILE:
945 peExt.fobj = fCookie.fobj
946 peExt.Path = BytePtrToString((*byte)(unsafe.Pointer(peExt.fobj.Name)))
947 // Only remove the paths entry if it exists and this cookie matches
948 if fobj, ok := e.paths[peExt.Path]; ok {
949 if fobj == fCookie {
950 delete(e.paths, peExt.Path)
951 }
952 }
953 }
954 return nil
955}
956
957// Pending wraps port_getn(3c) and returns how many events are pending.
958func (e *EventPort) Pending() (int, error) {
959 var n uint32 = 0
960 _, err := port_getn(e.port, nil, 0, &n, nil)
961 return int(n), err
962}
963
964// Get wraps port_getn(3c) and fills a slice of PortEvent.
965// It will block until either min events have been received
966// or the timeout has been exceeded. It will return how many
967// events were actually received along with any error information.
968func (e *EventPort) Get(s []PortEvent, min int, timeout *Timespec) (int, error) {
969 if min == 0 {
970 return 0, fmt.Errorf("need to request at least one event or use Pending() instead")
971 }
972 if len(s) < min {
973 return 0, fmt.Errorf("len(s) (%d) is less than min events requested (%d)", len(s), min)
974 }
975 got := uint32(min)
976 max := uint32(len(s))
977 var err error
978 ps := make([]portEvent, max)
979 _, err = port_getn(e.port, &ps[0], max, &got, timeout)
980 // got will be trustworthy with ETIME, but not any other error.
981 if err != nil && err != ETIME {
982 return 0, err
983 }
984 e.mu.Lock()
985 defer e.mu.Unlock()
986 valid := 0
987 for i := 0; i < int(got); i++ {
988 err2 := e.peIntToExt(&ps[i], &s[i])
989 if err2 != nil {
990 if valid == 0 && err == nil {
991 // If err2 is the only error and there are no valid events
992 // to return, return it to the caller.
993 err = err2
994 }
995 break
996 }
997 valid = i + 1
998 }
999 return valid, err
1000}
1001
1002//sys putmsg(fd int, clptr *strbuf, dataptr *strbuf, flags int) (err error)
1003
1004func Putmsg(fd int, cl []byte, data []byte, flags int) (err error) {
1005 var clp, datap *strbuf
1006 if len(cl) > 0 {
1007 clp = &strbuf{
1008 Len: int32(len(cl)),
1009 Buf: (*int8)(unsafe.Pointer(&cl[0])),
1010 }
1011 }
1012 if len(data) > 0 {
1013 datap = &strbuf{
1014 Len: int32(len(data)),
1015 Buf: (*int8)(unsafe.Pointer(&data[0])),
1016 }
1017 }
1018 return putmsg(fd, clp, datap, flags)
1019}
1020
1021//sys getmsg(fd int, clptr *strbuf, dataptr *strbuf, flags *int) (err error)
1022
1023func Getmsg(fd int, cl []byte, data []byte) (retCl []byte, retData []byte, flags int, err error) {
1024 var clp, datap *strbuf
1025 if len(cl) > 0 {
1026 clp = &strbuf{
1027 Maxlen: int32(len(cl)),
1028 Buf: (*int8)(unsafe.Pointer(&cl[0])),
1029 }
1030 }
1031 if len(data) > 0 {
1032 datap = &strbuf{
1033 Maxlen: int32(len(data)),
1034 Buf: (*int8)(unsafe.Pointer(&data[0])),
1035 }
1036 }
1037
1038 if err = getmsg(fd, clp, datap, &flags); err != nil {
1039 return nil, nil, 0, err
1040 }
1041
1042 if len(cl) > 0 {
1043 retCl = cl[:clp.Len]
1044 }
1045 if len(data) > 0 {
1046 retData = data[:datap.Len]
1047 }
1048 return retCl, retData, flags, nil
1049}
1050
1051func IoctlSetIntRetInt(fd int, req int, arg int) (int, error) {
1052 return ioctlRet(fd, req, uintptr(arg))
1053}
1054
1055func IoctlSetString(fd int, req int, val string) error {
1056 bs := make([]byte, len(val)+1)
1057 copy(bs[:len(bs)-1], val)
1058 err := ioctlPtr(fd, req, unsafe.Pointer(&bs[0]))
1059 runtime.KeepAlive(&bs[0])
1060 return err
1061}
1062
1063// Lifreq Helpers
1064
1065func (l *Lifreq) SetName(name string) error {
1066 if len(name) >= len(l.Name) {
1067 return fmt.Errorf("name cannot be more than %d characters", len(l.Name)-1)
1068 }
1069 for i := range name {
1070 l.Name[i] = int8(name[i])
1071 }
1072 return nil
1073}
1074
1075func (l *Lifreq) SetLifruInt(d int) {
1076 *(*int)(unsafe.Pointer(&l.Lifru[0])) = d
1077}
1078
1079func (l *Lifreq) GetLifruInt() int {
1080 return *(*int)(unsafe.Pointer(&l.Lifru[0]))
1081}
1082
1083func (l *Lifreq) SetLifruUint(d uint) {
1084 *(*uint)(unsafe.Pointer(&l.Lifru[0])) = d
1085}
1086
1087func (l *Lifreq) GetLifruUint() uint {
1088 return *(*uint)(unsafe.Pointer(&l.Lifru[0]))
1089}
1090
1091func IoctlLifreq(fd int, req int, l *Lifreq) error {
1092 return ioctlPtr(fd, req, unsafe.Pointer(l))
1093}
1094
1095// Strioctl Helpers
1096
1097func (s *Strioctl) SetInt(i int) {
1098 s.Len = int32(unsafe.Sizeof(i))
1099 s.Dp = (*int8)(unsafe.Pointer(&i))
1100}
1101
1102func IoctlSetStrioctlRetInt(fd int, req int, s *Strioctl) (int, error) {
1103 return ioctlPtrRet(fd, req, unsafe.Pointer(s))
1104}