1
2
3
4
5
6
7
8
9
10
11
12
13 package unix
14
15 import (
16 "fmt"
17 "os"
18 "runtime"
19 "sync"
20 "syscall"
21 "unsafe"
22 )
23
24
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
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
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
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
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
133 sa.raw.Path[0] = 0
134
135 sl--
136 }
137
138 return unsafe.Pointer(&sa.raw), sl, nil
139 }
140
141
142
143 func 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
153
154 func 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
164 const ImplementsGetwd = true
165
166
167
168 func Getwd() (wd string, err error) {
169 var buf [PathMax]byte
170
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
185
186
187
188
189 func Getgroups() (gids []int, err error) {
190 n, err := getgroups(0, nil)
191
192
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
214 func 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
227 func ReadDirent(fd int, buf []byte) (n int, err error) {
228
229
230 return Getdents(fd, buf, new(uintptr))
231 }
232
233
234
235
236
237
238
239 type WaitStatus uint32
240
241 const (
242 mask = 0x7F
243 core = 0x80
244 shift = 8
245
246 exited = 0
247 stopped = 0x7F
248 )
249
250 func (w WaitStatus) Exited() bool { return w&mask == exited }
251
252 func (w WaitStatus) ExitStatus() int {
253 if w&mask != exited {
254 return -1
255 }
256 return int(w >> shift)
257 }
258
259 func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 }
260
261 func (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
269 func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
270
271 func (w WaitStatus) Stopped() bool { return w&mask == stopped && syscall.Signal(w>>shift) != SIGSTOP }
272
273 func (w WaitStatus) Continued() bool { return w&mask == stopped && syscall.Signal(w>>shift) == SIGSTOP }
274
275 func (w WaitStatus) StopSignal() syscall.Signal {
276 if !w.Stopped() {
277 return -1
278 }
279 return syscall.Signal(w>>shift) & 0xFF
280 }
281
282 func (w WaitStatus) TrapCause() int { return -1 }
283
284
285
286 func 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
300
301 func 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
315
316 func 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
327
328 func 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
338 func 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
349
350
351 func 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
361 func 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
370
371 func 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
386
387
388 func 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
398 func 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
404
405
406
407
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
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
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
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
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
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
513
514 func Acct(path string) (err error) {
515 if len(path) == 0 {
516
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
528
529 func Mkdev(major, minor uint32) uint64 {
530 return __makedev(NEWDEV, uint(major), uint(minor))
531 }
532
533
534
535 func Major(dev uint64) uint32 {
536 return uint32(__major(NEWDEV, dev))
537 }
538
539
540
541 func Minor(dev uint64) uint32 {
542 return uint32(__minor(NEWDEV, dev))
543 }
544
545
548
549
550
551
552 func ioctl(fd int, req int, arg uintptr) (err error) {
553 _, err = ioctlRet(fd, req, arg)
554 return err
555 }
556
557 func ioctlPtr(fd int, req int, arg unsafe.Pointer) (err error) {
558 _, err = ioctlPtrRet(fd, req, arg)
559 return err
560 }
561
562 func IoctlSetTermio(fd int, req int, value *Termio) error {
563 return ioctlPtr(fd, req, unsafe.Pointer(value))
564 }
565
566 func 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
573
574 func 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
581 func 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
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704 type fileObjCookie struct {
705 fobj *fileObj
706 cookie interface{}
707 }
708
709
710 type EventPort struct {
711 port int
712 mu sync.Mutex
713 fds map[uintptr]*fileObjCookie
714 paths map[string]*fileObjCookie
715
716
717
718
719
720
721
722
723
724
725
726 cookies map[*fileObjCookie]struct{}
727 }
728
729
730
731
732
733 type PortEvent struct {
734 Cookie interface{}
735 Events int32
736 Fd uintptr
737 Path string
738 Source uint16
739 fobj *fileObj
740 }
741
742
743
744 func 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
759
760
761
762
763
764
765 func (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
779 func (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
787 func (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
795
796 func (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
816 func (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
825
826
827 if err != nil && err != ENOENT {
828 return err
829 }
830 if err == nil {
831
832 fCookie := e.paths[path]
833 delete(e.cookies, fCookie)
834 }
835 delete(e.paths, path)
836 return err
837 }
838
839
840 func (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
860 func (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
873 fCookie := e.fds[fd]
874 delete(e.cookies, fCookie)
875 }
876 delete(e.fds, fd)
877 return err
878 }
879
880 func 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
902 func (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
919
920 func (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
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
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
958 func (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
965
966
967
968 func (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
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
992
993 err = err2
994 }
995 break
996 }
997 valid = i + 1
998 }
999 return valid, err
1000 }
1001
1002
1003
1004 func 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
1022
1023 func 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
1051 func IoctlSetIntRetInt(fd int, req int, arg int) (int, error) {
1052 return ioctlRet(fd, req, uintptr(arg))
1053 }
1054
1055 func 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
1064
1065 func (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
1075 func (l *Lifreq) SetLifruInt(d int) {
1076 *(*int)(unsafe.Pointer(&l.Lifru[0])) = d
1077 }
1078
1079 func (l *Lifreq) GetLifruInt() int {
1080 return *(*int)(unsafe.Pointer(&l.Lifru[0]))
1081 }
1082
1083 func (l *Lifreq) SetLifruUint(d uint) {
1084 *(*uint)(unsafe.Pointer(&l.Lifru[0])) = d
1085 }
1086
1087 func (l *Lifreq) GetLifruUint() uint {
1088 return *(*uint)(unsafe.Pointer(&l.Lifru[0]))
1089 }
1090
1091 func IoctlLifreq(fd int, req int, l *Lifreq) error {
1092 return ioctlPtr(fd, req, unsafe.Pointer(l))
1093 }
1094
1095
1096
1097 func (s *Strioctl) SetInt(i int) {
1098 s.Len = int32(unsafe.Sizeof(i))
1099 s.Dp = (*int8)(unsafe.Pointer(&i))
1100 }
1101
1102 func IoctlSetStrioctlRetInt(fd int, req int, s *Strioctl) (int, error) {
1103 return ioctlPtrRet(fd, req, unsafe.Pointer(s))
1104 }
1105
View as plain text