comparison vendor/golang.org/x/sys/unix/syscall_solaris.go @ 66:787b5ee0289d draft

Use vendored modules Signed-off-by: Izuru Yakumo <yakumo.izuru@chaotic.ninja>
author yakumo.izuru
date Sun, 23 Jul 2023 13:18:53 +0000
parents
children 4b79810863f6
comparison
equal deleted inserted replaced
65:6d985efa0f7a 66:787b5ee0289d
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
13 package unix
14
15 import (
16 "fmt"
17 "os"
18 "runtime"
19 "sync"
20 "syscall"
21 "unsafe"
22 )
23
24 // Implemented in runtime/syscall_solaris.go.
25 type syscallFunc uintptr
26
27 func rawSysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno)
28 func 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.
31 type 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
42 func direntIno(buf []byte) (uint64, bool) {
43 return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
44 }
45
46 func direntReclen(buf []byte) (uint64, bool) {
47 return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
48 }
49
50 func 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
60 func 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
78 func 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
91 func (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
103 func (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
116 func (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
142 func 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.
153 func 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
163 const ImplementsGetwd = true
164
165 //sys Getcwd(buf []byte) (n int, err error)
166
167 func 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
188 func 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
213 func 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.
226 func 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
238 type WaitStatus uint32
239
240 const (
241 mask = 0x7F
242 core = 0x80
243 shift = 8
244
245 exited = 0
246 stopped = 0x7F
247 )
248
249 func (w WaitStatus) Exited() bool { return w&mask == exited }
250
251 func (w WaitStatus) ExitStatus() int {
252 if w&mask != exited {
253 return -1
254 }
255 return int(w >> shift)
256 }
257
258 func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 }
259
260 func (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
268 func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
269
270 func (w WaitStatus) Stopped() bool { return w&mask == stopped && syscall.Signal(w>>shift) != SIGSTOP }
271
272 func (w WaitStatus) Continued() bool { return w&mask == stopped && syscall.Signal(w>>shift) == SIGSTOP }
273
274 func (w WaitStatus) StopSignal() syscall.Signal {
275 if !w.Stopped() {
276 return -1
277 }
278 return syscall.Signal(w>>shift) & 0xFF
279 }
280
281 func (w WaitStatus) TrapCause() int { return -1 }
282
283 //sys wait4(pid int32, statusp *_C_int, options int, rusage *Rusage) (wpid int32, err error)
284
285 func 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
300 func 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
315 func 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
327 func 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
337 func 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.
350 func 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.
360 func 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
370 func 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.
387 func 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
397 func 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 bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
412 sa.Name = string(bytes)
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
437 func 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
454 func 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
482 func 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
514 func 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
529 func 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
535 func Major(dev uint64) uint32 {
536 return uint32(__major(NEWDEV, dev))
537 }
538
539 //sys __minor(version int, dev uint64) (val uint)
540
541 func 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 uint, arg uintptr) (ret int, err error) = libc.ioctl
550
551 func ioctl(fd int, req uint, arg uintptr) (err error) {
552 _, err = ioctlRet(fd, req, arg)
553 return err
554 }
555
556 func IoctlSetTermio(fd int, req uint, value *Termio) error {
557 err := ioctl(fd, req, uintptr(unsafe.Pointer(value)))
558 runtime.KeepAlive(value)
559 return err
560 }
561
562 func IoctlGetTermio(fd int, req uint) (*Termio, error) {
563 var value Termio
564 err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
565 return &value, err
566 }
567
568 //sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
569
570 func Poll(fds []PollFd, timeout int) (n int, err error) {
571 if len(fds) == 0 {
572 return poll(nil, 0, timeout)
573 }
574 return poll(&fds[0], len(fds), timeout)
575 }
576
577 func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
578 if raceenabled {
579 raceReleaseMerge(unsafe.Pointer(&ioSync))
580 }
581 return sendfile(outfd, infd, offset, count)
582 }
583
584 /*
585 * Exposed directly
586 */
587 //sys Access(path string, mode uint32) (err error)
588 //sys Adjtime(delta *Timeval, olddelta *Timeval) (err error)
589 //sys Chdir(path string) (err error)
590 //sys Chmod(path string, mode uint32) (err error)
591 //sys Chown(path string, uid int, gid int) (err error)
592 //sys Chroot(path string) (err error)
593 //sys Close(fd int) (err error)
594 //sys Creat(path string, mode uint32) (fd int, err error)
595 //sys Dup(fd int) (nfd int, err error)
596 //sys Dup2(oldfd int, newfd int) (err error)
597 //sys Exit(code int)
598 //sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error)
599 //sys Fchdir(fd int) (err error)
600 //sys Fchmod(fd int, mode uint32) (err error)
601 //sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
602 //sys Fchown(fd int, uid int, gid int) (err error)
603 //sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
604 //sys Fdatasync(fd int) (err error)
605 //sys Flock(fd int, how int) (err error)
606 //sys Fpathconf(fd int, name int) (val int, err error)
607 //sys Fstat(fd int, stat *Stat_t) (err error)
608 //sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
609 //sys Fstatvfs(fd int, vfsstat *Statvfs_t) (err error)
610 //sys Getdents(fd int, buf []byte, basep *uintptr) (n int, err error)
611 //sysnb Getgid() (gid int)
612 //sysnb Getpid() (pid int)
613 //sysnb Getpgid(pid int) (pgid int, err error)
614 //sysnb Getpgrp() (pgid int, err error)
615 //sys Geteuid() (euid int)
616 //sys Getegid() (egid int)
617 //sys Getppid() (ppid int)
618 //sys Getpriority(which int, who int) (n int, err error)
619 //sysnb Getrlimit(which int, lim *Rlimit) (err error)
620 //sysnb Getrusage(who int, rusage *Rusage) (err error)
621 //sysnb Getsid(pid int) (sid int, err error)
622 //sysnb Gettimeofday(tv *Timeval) (err error)
623 //sysnb Getuid() (uid int)
624 //sys Kill(pid int, signum syscall.Signal) (err error)
625 //sys Lchown(path string, uid int, gid int) (err error)
626 //sys Link(path string, link string) (err error)
627 //sys Listen(s int, backlog int) (err error) = libsocket.__xnet_llisten
628 //sys Lstat(path string, stat *Stat_t) (err error)
629 //sys Madvise(b []byte, advice int) (err error)
630 //sys Mkdir(path string, mode uint32) (err error)
631 //sys Mkdirat(dirfd int, path string, mode uint32) (err error)
632 //sys Mkfifo(path string, mode uint32) (err error)
633 //sys Mkfifoat(dirfd int, path string, mode uint32) (err error)
634 //sys Mknod(path string, mode uint32, dev int) (err error)
635 //sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error)
636 //sys Mlock(b []byte) (err error)
637 //sys Mlockall(flags int) (err error)
638 //sys Mprotect(b []byte, prot int) (err error)
639 //sys Msync(b []byte, flags int) (err error)
640 //sys Munlock(b []byte) (err error)
641 //sys Munlockall() (err error)
642 //sys Nanosleep(time *Timespec, leftover *Timespec) (err error)
643 //sys Open(path string, mode int, perm uint32) (fd int, err error)
644 //sys Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
645 //sys Pathconf(path string, name int) (val int, err error)
646 //sys Pause() (err error)
647 //sys pread(fd int, p []byte, offset int64) (n int, err error)
648 //sys pwrite(fd int, p []byte, offset int64) (n int, err error)
649 //sys read(fd int, p []byte) (n int, err error)
650 //sys Readlink(path string, buf []byte) (n int, err error)
651 //sys Rename(from string, to string) (err error)
652 //sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error)
653 //sys Rmdir(path string) (err error)
654 //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = lseek
655 //sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error)
656 //sysnb Setegid(egid int) (err error)
657 //sysnb Seteuid(euid int) (err error)
658 //sysnb Setgid(gid int) (err error)
659 //sys Sethostname(p []byte) (err error)
660 //sysnb Setpgid(pid int, pgid int) (err error)
661 //sys Setpriority(which int, who int, prio int) (err error)
662 //sysnb Setregid(rgid int, egid int) (err error)
663 //sysnb Setreuid(ruid int, euid int) (err error)
664 //sysnb Setrlimit(which int, lim *Rlimit) (err error)
665 //sysnb Setsid() (pid int, err error)
666 //sysnb Setuid(uid int) (err error)
667 //sys Shutdown(s int, how int) (err error) = libsocket.shutdown
668 //sys Stat(path string, stat *Stat_t) (err error)
669 //sys Statvfs(path string, vfsstat *Statvfs_t) (err error)
670 //sys Symlink(path string, link string) (err error)
671 //sys Sync() (err error)
672 //sys Sysconf(which int) (n int64, err error)
673 //sysnb Times(tms *Tms) (ticks uintptr, err error)
674 //sys Truncate(path string, length int64) (err error)
675 //sys Fsync(fd int) (err error)
676 //sys Ftruncate(fd int, length int64) (err error)
677 //sys Umask(mask int) (oldmask int)
678 //sysnb Uname(buf *Utsname) (err error)
679 //sys Unmount(target string, flags int) (err error) = libc.umount
680 //sys Unlink(path string) (err error)
681 //sys Unlinkat(dirfd int, path string, flags int) (err error)
682 //sys Ustat(dev int, ubuf *Ustat_t) (err error)
683 //sys Utime(path string, buf *Utimbuf) (err error)
684 //sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_bind
685 //sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_connect
686 //sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
687 //sys munmap(addr uintptr, length uintptr) (err error)
688 //sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = libsendfile.sendfile
689 //sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) = libsocket.__xnet_sendto
690 //sys socket(domain int, typ int, proto int) (fd int, err error) = libsocket.__xnet_socket
691 //sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) = libsocket.__xnet_socketpair
692 //sys write(fd int, p []byte) (n int, err error)
693 //sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) = libsocket.__xnet_getsockopt
694 //sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) = libsocket.getpeername
695 //sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) = libsocket.setsockopt
696 //sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) = libsocket.recvfrom
697
698 func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
699 r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procread)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
700 n = int(r0)
701 if e1 != 0 {
702 err = e1
703 }
704 return
705 }
706
707 func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
708 r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procwrite)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
709 n = int(r0)
710 if e1 != 0 {
711 err = e1
712 }
713 return
714 }
715
716 var mapper = &mmapper{
717 active: make(map[*byte][]byte),
718 mmap: mmap,
719 munmap: munmap,
720 }
721
722 func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
723 return mapper.Mmap(fd, offset, length, prot, flags)
724 }
725
726 func Munmap(b []byte) (err error) {
727 return mapper.Munmap(b)
728 }
729
730 // Event Ports
731
732 type fileObjCookie struct {
733 fobj *fileObj
734 cookie interface{}
735 }
736
737 // EventPort provides a safe abstraction on top of Solaris/illumos Event Ports.
738 type EventPort struct {
739 port int
740 mu sync.Mutex
741 fds map[uintptr]*fileObjCookie
742 paths map[string]*fileObjCookie
743 // The user cookie presents an interesting challenge from a memory management perspective.
744 // There are two paths by which we can discover that it is no longer in use:
745 // 1. The user calls port_dissociate before any events fire
746 // 2. An event fires and we return it to the user
747 // The tricky situation is if the event has fired in the kernel but
748 // the user hasn't requested/received it yet.
749 // If the user wants to port_dissociate before the event has been processed,
750 // we should handle things gracefully. To do so, we need to keep an extra
751 // reference to the cookie around until the event is processed
752 // thus the otherwise seemingly extraneous "cookies" map
753 // The key of this map is a pointer to the corresponding &fCookie.cookie
754 cookies map[*interface{}]*fileObjCookie
755 }
756
757 // PortEvent is an abstraction of the port_event C struct.
758 // Compare Source against PORT_SOURCE_FILE or PORT_SOURCE_FD
759 // to see if Path or Fd was the event source. The other will be
760 // uninitialized.
761 type PortEvent struct {
762 Cookie interface{}
763 Events int32
764 Fd uintptr
765 Path string
766 Source uint16
767 fobj *fileObj
768 }
769
770 // NewEventPort creates a new EventPort including the
771 // underlying call to port_create(3c).
772 func NewEventPort() (*EventPort, error) {
773 port, err := port_create()
774 if err != nil {
775 return nil, err
776 }
777 e := &EventPort{
778 port: port,
779 fds: make(map[uintptr]*fileObjCookie),
780 paths: make(map[string]*fileObjCookie),
781 cookies: make(map[*interface{}]*fileObjCookie),
782 }
783 return e, nil
784 }
785
786 //sys port_create() (n int, err error)
787 //sys port_associate(port int, source int, object uintptr, events int, user *byte) (n int, err error)
788 //sys port_dissociate(port int, source int, object uintptr) (n int, err error)
789 //sys port_get(port int, pe *portEvent, timeout *Timespec) (n int, err error)
790 //sys port_getn(port int, pe *portEvent, max uint32, nget *uint32, timeout *Timespec) (n int, err error)
791
792 // Close closes the event port.
793 func (e *EventPort) Close() error {
794 e.mu.Lock()
795 defer e.mu.Unlock()
796 err := Close(e.port)
797 if err != nil {
798 return err
799 }
800 e.fds = nil
801 e.paths = nil
802 return nil
803 }
804
805 // PathIsWatched checks to see if path is associated with this EventPort.
806 func (e *EventPort) PathIsWatched(path string) bool {
807 e.mu.Lock()
808 defer e.mu.Unlock()
809 _, found := e.paths[path]
810 return found
811 }
812
813 // FdIsWatched checks to see if fd is associated with this EventPort.
814 func (e *EventPort) FdIsWatched(fd uintptr) bool {
815 e.mu.Lock()
816 defer e.mu.Unlock()
817 _, found := e.fds[fd]
818 return found
819 }
820
821 // AssociatePath wraps port_associate(3c) for a filesystem path including
822 // creating the necessary file_obj from the provided stat information.
823 func (e *EventPort) AssociatePath(path string, stat os.FileInfo, events int, cookie interface{}) error {
824 e.mu.Lock()
825 defer e.mu.Unlock()
826 if _, found := e.paths[path]; found {
827 return fmt.Errorf("%v is already associated with this Event Port", path)
828 }
829 fobj, err := createFileObj(path, stat)
830 if err != nil {
831 return err
832 }
833 fCookie := &fileObjCookie{fobj, cookie}
834 _, err = port_associate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(fobj)), events, (*byte)(unsafe.Pointer(&fCookie.cookie)))
835 if err != nil {
836 return err
837 }
838 e.paths[path] = fCookie
839 e.cookies[&fCookie.cookie] = fCookie
840 return nil
841 }
842
843 // DissociatePath wraps port_dissociate(3c) for a filesystem path.
844 func (e *EventPort) DissociatePath(path string) error {
845 e.mu.Lock()
846 defer e.mu.Unlock()
847 f, ok := e.paths[path]
848 if !ok {
849 return fmt.Errorf("%v is not associated with this Event Port", path)
850 }
851 _, err := port_dissociate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(f.fobj)))
852 // If the path is no longer associated with this event port (ENOENT)
853 // we should delete it from our map. We can still return ENOENT to the caller.
854 // But we need to save the cookie
855 if err != nil && err != ENOENT {
856 return err
857 }
858 if err == nil {
859 // dissociate was successful, safe to delete the cookie
860 fCookie := e.paths[path]
861 delete(e.cookies, &fCookie.cookie)
862 }
863 delete(e.paths, path)
864 return err
865 }
866
867 // AssociateFd wraps calls to port_associate(3c) on file descriptors.
868 func (e *EventPort) AssociateFd(fd uintptr, events int, cookie interface{}) error {
869 e.mu.Lock()
870 defer e.mu.Unlock()
871 if _, found := e.fds[fd]; found {
872 return fmt.Errorf("%v is already associated with this Event Port", fd)
873 }
874 fCookie := &fileObjCookie{nil, cookie}
875 _, err := port_associate(e.port, PORT_SOURCE_FD, fd, events, (*byte)(unsafe.Pointer(&fCookie.cookie)))
876 if err != nil {
877 return err
878 }
879 e.fds[fd] = fCookie
880 e.cookies[&fCookie.cookie] = fCookie
881 return nil
882 }
883
884 // DissociateFd wraps calls to port_dissociate(3c) on file descriptors.
885 func (e *EventPort) DissociateFd(fd uintptr) error {
886 e.mu.Lock()
887 defer e.mu.Unlock()
888 _, ok := e.fds[fd]
889 if !ok {
890 return fmt.Errorf("%v is not associated with this Event Port", fd)
891 }
892 _, err := port_dissociate(e.port, PORT_SOURCE_FD, fd)
893 if err != nil && err != ENOENT {
894 return err
895 }
896 if err == nil {
897 // dissociate was successful, safe to delete the cookie
898 fCookie := e.fds[fd]
899 delete(e.cookies, &fCookie.cookie)
900 }
901 delete(e.fds, fd)
902 return err
903 }
904
905 func createFileObj(name string, stat os.FileInfo) (*fileObj, error) {
906 fobj := new(fileObj)
907 bs, err := ByteSliceFromString(name)
908 if err != nil {
909 return nil, err
910 }
911 fobj.Name = (*int8)(unsafe.Pointer(&bs[0]))
912 s := stat.Sys().(*syscall.Stat_t)
913 fobj.Atim.Sec = s.Atim.Sec
914 fobj.Atim.Nsec = s.Atim.Nsec
915 fobj.Mtim.Sec = s.Mtim.Sec
916 fobj.Mtim.Nsec = s.Mtim.Nsec
917 fobj.Ctim.Sec = s.Ctim.Sec
918 fobj.Ctim.Nsec = s.Ctim.Nsec
919 return fobj, nil
920 }
921
922 // GetOne wraps port_get(3c) and returns a single PortEvent.
923 func (e *EventPort) GetOne(t *Timespec) (*PortEvent, error) {
924 pe := new(portEvent)
925 _, err := port_get(e.port, pe, t)
926 if err != nil {
927 return nil, err
928 }
929 p := new(PortEvent)
930 e.mu.Lock()
931 defer e.mu.Unlock()
932 e.peIntToExt(pe, p)
933 return p, nil
934 }
935
936 // peIntToExt converts a cgo portEvent struct into the friendlier PortEvent
937 // NOTE: Always call this function while holding the e.mu mutex
938 func (e *EventPort) peIntToExt(peInt *portEvent, peExt *PortEvent) {
939 peExt.Events = peInt.Events
940 peExt.Source = peInt.Source
941 cookie := (*interface{})(unsafe.Pointer(peInt.User))
942 peExt.Cookie = *cookie
943 switch peInt.Source {
944 case PORT_SOURCE_FD:
945 delete(e.cookies, cookie)
946 peExt.Fd = uintptr(peInt.Object)
947 // Only remove the fds entry if it exists and this cookie matches
948 if fobj, ok := e.fds[peExt.Fd]; ok {
949 if &fobj.cookie == cookie {
950 delete(e.fds, peExt.Fd)
951 }
952 }
953 case PORT_SOURCE_FILE:
954 if fCookie, ok := e.cookies[cookie]; ok && uintptr(unsafe.Pointer(fCookie.fobj)) == uintptr(peInt.Object) {
955 // Use our stashed reference rather than using unsafe on what we got back
956 // the unsafe version would be (*fileObj)(unsafe.Pointer(uintptr(peInt.Object)))
957 peExt.fobj = fCookie.fobj
958 } else {
959 panic("mismanaged memory")
960 }
961 delete(e.cookies, cookie)
962 peExt.Path = BytePtrToString((*byte)(unsafe.Pointer(peExt.fobj.Name)))
963 // Only remove the paths entry if it exists and this cookie matches
964 if fobj, ok := e.paths[peExt.Path]; ok {
965 if &fobj.cookie == cookie {
966 delete(e.paths, peExt.Path)
967 }
968 }
969 }
970 }
971
972 // Pending wraps port_getn(3c) and returns how many events are pending.
973 func (e *EventPort) Pending() (int, error) {
974 var n uint32 = 0
975 _, err := port_getn(e.port, nil, 0, &n, nil)
976 return int(n), err
977 }
978
979 // Get wraps port_getn(3c) and fills a slice of PortEvent.
980 // It will block until either min events have been received
981 // or the timeout has been exceeded. It will return how many
982 // events were actually received along with any error information.
983 func (e *EventPort) Get(s []PortEvent, min int, timeout *Timespec) (int, error) {
984 if min == 0 {
985 return 0, fmt.Errorf("need to request at least one event or use Pending() instead")
986 }
987 if len(s) < min {
988 return 0, fmt.Errorf("len(s) (%d) is less than min events requested (%d)", len(s), min)
989 }
990 got := uint32(min)
991 max := uint32(len(s))
992 var err error
993 ps := make([]portEvent, max, max)
994 _, err = port_getn(e.port, &ps[0], max, &got, timeout)
995 // got will be trustworthy with ETIME, but not any other error.
996 if err != nil && err != ETIME {
997 return 0, err
998 }
999 e.mu.Lock()
1000 defer e.mu.Unlock()
1001 for i := 0; i < int(got); i++ {
1002 e.peIntToExt(&ps[i], &s[i])
1003 }
1004 return int(got), err
1005 }