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