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 p[0] = int(pp[0])
70 p[1] = int(pp[1])
71 return nil
72 }
73
74
75
76 func Pipe2(p []int, flags int) error {
77 if len(p) != 2 {
78 return EINVAL
79 }
80 var pp [2]_C_int
81 err := pipe2(&pp, flags)
82 p[0] = int(pp[0])
83 p[1] = int(pp[1])
84 return err
85 }
86
87 func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
88 if sa.Port < 0 || sa.Port > 0xFFFF {
89 return nil, 0, EINVAL
90 }
91 sa.raw.Family = AF_INET
92 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
93 p[0] = byte(sa.Port >> 8)
94 p[1] = byte(sa.Port)
95 sa.raw.Addr = sa.Addr
96 return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
97 }
98
99 func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
100 if sa.Port < 0 || sa.Port > 0xFFFF {
101 return nil, 0, EINVAL
102 }
103 sa.raw.Family = AF_INET6
104 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
105 p[0] = byte(sa.Port >> 8)
106 p[1] = byte(sa.Port)
107 sa.raw.Scope_id = sa.ZoneId
108 sa.raw.Addr = sa.Addr
109 return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
110 }
111
112 func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) {
113 name := sa.Name
114 n := len(name)
115 if n >= len(sa.raw.Path) {
116 return nil, 0, EINVAL
117 }
118 sa.raw.Family = AF_UNIX
119 for i := 0; i < n; i++ {
120 sa.raw.Path[i] = int8(name[i])
121 }
122
123 sl := _Socklen(2)
124 if n > 0 {
125 sl += _Socklen(n) + 1
126 }
127 if sa.raw.Path[0] == '@' {
128 sa.raw.Path[0] = 0
129
130 sl--
131 }
132
133 return unsafe.Pointer(&sa.raw), sl, nil
134 }
135
136
137
138 func Getsockname(fd int) (sa Sockaddr, err error) {
139 var rsa RawSockaddrAny
140 var len _Socklen = SizeofSockaddrAny
141 if err = getsockname(fd, &rsa, &len); err != nil {
142 return
143 }
144 return anyToSockaddr(fd, &rsa)
145 }
146
147
148
149 func GetsockoptString(fd, level, opt int) (string, error) {
150 buf := make([]byte, 256)
151 vallen := _Socklen(len(buf))
152 err := getsockopt(fd, level, opt, unsafe.Pointer(&buf[0]), &vallen)
153 if err != nil {
154 return "", err
155 }
156 return string(buf[:vallen-1]), nil
157 }
158
159 const ImplementsGetwd = true
160
161
162
163 func Getwd() (wd string, err error) {
164 var buf [PathMax]byte
165
166 _, err = Getcwd(buf[0:])
167 if err != nil {
168 return "", err
169 }
170 n := clen(buf[:])
171 if n < 1 {
172 return "", EINVAL
173 }
174 return string(buf[:n]), nil
175 }
176
177
180
181
182
183
184 func Getgroups() (gids []int, err error) {
185 n, err := getgroups(0, nil)
186
187
188 if n < 0 || n > 1024 {
189 if err != nil {
190 return nil, err
191 }
192 return nil, EINVAL
193 } else if n == 0 {
194 return nil, nil
195 }
196
197 a := make([]_Gid_t, n)
198 n, err = getgroups(n, &a[0])
199 if n == -1 {
200 return nil, err
201 }
202 gids = make([]int, n)
203 for i, v := range a[0:n] {
204 gids[i] = int(v)
205 }
206 return
207 }
208
209 func Setgroups(gids []int) (err error) {
210 if len(gids) == 0 {
211 return setgroups(0, nil)
212 }
213
214 a := make([]_Gid_t, len(gids))
215 for i, v := range gids {
216 a[i] = _Gid_t(v)
217 }
218 return setgroups(len(a), &a[0])
219 }
220
221
222 func ReadDirent(fd int, buf []byte) (n int, err error) {
223
224
225 return Getdents(fd, buf, new(uintptr))
226 }
227
228
229
230
231
232
233
234 type WaitStatus uint32
235
236 const (
237 mask = 0x7F
238 core = 0x80
239 shift = 8
240
241 exited = 0
242 stopped = 0x7F
243 )
244
245 func (w WaitStatus) Exited() bool { return w&mask == exited }
246
247 func (w WaitStatus) ExitStatus() int {
248 if w&mask != exited {
249 return -1
250 }
251 return int(w >> shift)
252 }
253
254 func (w WaitStatus) Signaled() bool { return w&mask != stopped && w&mask != 0 }
255
256 func (w WaitStatus) Signal() syscall.Signal {
257 sig := syscall.Signal(w & mask)
258 if sig == stopped || sig == 0 {
259 return -1
260 }
261 return sig
262 }
263
264 func (w WaitStatus) CoreDump() bool { return w.Signaled() && w&core != 0 }
265
266 func (w WaitStatus) Stopped() bool { return w&mask == stopped && syscall.Signal(w>>shift) != SIGSTOP }
267
268 func (w WaitStatus) Continued() bool { return w&mask == stopped && syscall.Signal(w>>shift) == SIGSTOP }
269
270 func (w WaitStatus) StopSignal() syscall.Signal {
271 if !w.Stopped() {
272 return -1
273 }
274 return syscall.Signal(w>>shift) & 0xFF
275 }
276
277 func (w WaitStatus) TrapCause() int { return -1 }
278
279
280
281 func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (int, error) {
282 var status _C_int
283 rpid, err := wait4(int32(pid), &status, options, rusage)
284 wpid := int(rpid)
285 if wpid == -1 {
286 return wpid, err
287 }
288 if wstatus != nil {
289 *wstatus = WaitStatus(status)
290 }
291 return wpid, nil
292 }
293
294
295
296 func Gethostname() (name string, err error) {
297 var buf [MaxHostNameLen]byte
298 n, err := gethostname(buf[:])
299 if n != 0 {
300 return "", err
301 }
302 n = clen(buf[:])
303 if n < 1 {
304 return "", EFAULT
305 }
306 return string(buf[:n]), nil
307 }
308
309
310
311 func Utimes(path string, tv []Timeval) (err error) {
312 if tv == nil {
313 return utimes(path, nil)
314 }
315 if len(tv) != 2 {
316 return EINVAL
317 }
318 return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
319 }
320
321
322
323 func UtimesNano(path string, ts []Timespec) error {
324 if ts == nil {
325 return utimensat(AT_FDCWD, path, nil, 0)
326 }
327 if len(ts) != 2 {
328 return EINVAL
329 }
330 return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
331 }
332
333 func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error {
334 if ts == nil {
335 return utimensat(dirfd, path, nil, flags)
336 }
337 if len(ts) != 2 {
338 return EINVAL
339 }
340 return utimensat(dirfd, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), flags)
341 }
342
343
344
345
346 func FcntlInt(fd uintptr, cmd, arg int) (int, error) {
347 valptr, _, errno := sysvicall6(uintptr(unsafe.Pointer(&procfcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(arg), 0, 0, 0)
348 var err error
349 if errno != 0 {
350 err = errno
351 }
352 return int(valptr), err
353 }
354
355
356 func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) error {
357 _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procfcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(lk)), 0, 0, 0)
358 if e1 != 0 {
359 return e1
360 }
361 return nil
362 }
363
364
365
366 func Futimesat(dirfd int, path string, tv []Timeval) error {
367 pathp, err := BytePtrFromString(path)
368 if err != nil {
369 return err
370 }
371 if tv == nil {
372 return futimesat(dirfd, pathp, nil)
373 }
374 if len(tv) != 2 {
375 return EINVAL
376 }
377 return futimesat(dirfd, pathp, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
378 }
379
380
381
382
383 func Futimes(fd int, tv []Timeval) error {
384 if tv == nil {
385 return futimesat(fd, nil, nil)
386 }
387 if len(tv) != 2 {
388 return EINVAL
389 }
390 return futimesat(fd, nil, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
391 }
392
393 func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
394 switch rsa.Addr.Family {
395 case AF_UNIX:
396 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
397 sa := new(SockaddrUnix)
398
399
400
401
402
403 n := 0
404 for n < len(pp.Path) && pp.Path[n] != 0 {
405 n++
406 }
407 bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n]
408 sa.Name = string(bytes)
409 return sa, nil
410
411 case AF_INET:
412 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
413 sa := new(SockaddrInet4)
414 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
415 sa.Port = int(p[0])<<8 + int(p[1])
416 sa.Addr = pp.Addr
417 return sa, nil
418
419 case AF_INET6:
420 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
421 sa := new(SockaddrInet6)
422 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
423 sa.Port = int(p[0])<<8 + int(p[1])
424 sa.ZoneId = pp.Scope_id
425 sa.Addr = pp.Addr
426 return sa, nil
427 }
428 return nil, EAFNOSUPPORT
429 }
430
431
432
433 func Accept(fd int) (nfd int, sa Sockaddr, err error) {
434 var rsa RawSockaddrAny
435 var len _Socklen = SizeofSockaddrAny
436 nfd, err = accept(fd, &rsa, &len)
437 if nfd == -1 {
438 return
439 }
440 sa, err = anyToSockaddr(fd, &rsa)
441 if err != nil {
442 Close(nfd)
443 nfd = 0
444 }
445 return
446 }
447
448
449
450 func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error) {
451 var msg Msghdr
452 var rsa RawSockaddrAny
453 msg.Name = (*byte)(unsafe.Pointer(&rsa))
454 msg.Namelen = uint32(SizeofSockaddrAny)
455 var iov Iovec
456 if len(p) > 0 {
457 iov.Base = (*int8)(unsafe.Pointer(&p[0]))
458 iov.SetLen(len(p))
459 }
460 var dummy int8
461 if len(oob) > 0 {
462
463 if len(p) == 0 {
464 iov.Base = &dummy
465 iov.SetLen(1)
466 }
467 msg.Accrightslen = int32(len(oob))
468 }
469 msg.Iov = &iov
470 msg.Iovlen = 1
471 if n, err = recvmsg(fd, &msg, flags); n == -1 {
472 return
473 }
474 oobn = int(msg.Accrightslen)
475
476 if rsa.Addr.Family != AF_UNSPEC {
477 from, err = anyToSockaddr(fd, &rsa)
478 }
479 return
480 }
481
482 func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error) {
483 _, err = SendmsgN(fd, p, oob, to, flags)
484 return
485 }
486
487
488
489 func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error) {
490 var ptr unsafe.Pointer
491 var salen _Socklen
492 if to != nil {
493 ptr, salen, err = to.sockaddr()
494 if err != nil {
495 return 0, err
496 }
497 }
498 var msg Msghdr
499 msg.Name = (*byte)(unsafe.Pointer(ptr))
500 msg.Namelen = uint32(salen)
501 var iov Iovec
502 if len(p) > 0 {
503 iov.Base = (*int8)(unsafe.Pointer(&p[0]))
504 iov.SetLen(len(p))
505 }
506 var dummy int8
507 if len(oob) > 0 {
508
509 if len(p) == 0 {
510 iov.Base = &dummy
511 iov.SetLen(1)
512 }
513 msg.Accrightslen = int32(len(oob))
514 }
515 msg.Iov = &iov
516 msg.Iovlen = 1
517 if n, err = sendmsg(fd, &msg, flags); err != nil {
518 return 0, err
519 }
520 if len(oob) > 0 && len(p) == 0 {
521 n = 0
522 }
523 return n, nil
524 }
525
526
527
528 func Acct(path string) (err error) {
529 if len(path) == 0 {
530
531 return acct(nil)
532 }
533
534 pathp, err := BytePtrFromString(path)
535 if err != nil {
536 return err
537 }
538 return acct(pathp)
539 }
540
541
542
543 func Mkdev(major, minor uint32) uint64 {
544 return __makedev(NEWDEV, uint(major), uint(minor))
545 }
546
547
548
549 func Major(dev uint64) uint32 {
550 return uint32(__major(NEWDEV, dev))
551 }
552
553
554
555 func Minor(dev uint64) uint32 {
556 return uint32(__minor(NEWDEV, dev))
557 }
558
559
562
563
564
565 func ioctl(fd int, req uint, arg uintptr) (err error) {
566 _, err = ioctlRet(fd, req, arg)
567 return err
568 }
569
570 func IoctlSetTermio(fd int, req uint, value *Termio) error {
571 err := ioctl(fd, req, uintptr(unsafe.Pointer(value)))
572 runtime.KeepAlive(value)
573 return err
574 }
575
576 func IoctlGetTermio(fd int, req uint) (*Termio, error) {
577 var value Termio
578 err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
579 return &value, err
580 }
581
582
583
584 func Poll(fds []PollFd, timeout int) (n int, err error) {
585 if len(fds) == 0 {
586 return poll(nil, 0, timeout)
587 }
588 return poll(&fds[0], len(fds), timeout)
589 }
590
591 func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
592 if raceenabled {
593 raceReleaseMerge(unsafe.Pointer(&ioSync))
594 }
595 return sendfile(outfd, infd, offset, count)
596 }
597
598
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
705
706
707
708
709
710
711 func readlen(fd int, buf *byte, nbuf int) (n int, err error) {
712 r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procread)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
713 n = int(r0)
714 if e1 != 0 {
715 err = e1
716 }
717 return
718 }
719
720 func writelen(fd int, buf *byte, nbuf int) (n int, err error) {
721 r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procwrite)), 3, uintptr(fd), uintptr(unsafe.Pointer(buf)), uintptr(nbuf), 0, 0, 0)
722 n = int(r0)
723 if e1 != 0 {
724 err = e1
725 }
726 return
727 }
728
729 var mapper = &mmapper{
730 active: make(map[*byte][]byte),
731 mmap: mmap,
732 munmap: munmap,
733 }
734
735 func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
736 return mapper.Mmap(fd, offset, length, prot, flags)
737 }
738
739 func Munmap(b []byte) (err error) {
740 return mapper.Munmap(b)
741 }
742
743
744
745 type fileObjCookie struct {
746 fobj *fileObj
747 cookie interface{}
748 }
749
750
751 type EventPort struct {
752 port int
753 mu sync.Mutex
754 fds map[uintptr]interface{}
755 paths map[string]*fileObjCookie
756 }
757
758
759
760
761
762 type PortEvent struct {
763 Cookie interface{}
764 Events int32
765 Fd uintptr
766 Path string
767 Source uint16
768 fobj *fileObj
769 }
770
771
772
773 func NewEventPort() (*EventPort, error) {
774 port, err := port_create()
775 if err != nil {
776 return nil, err
777 }
778 e := &EventPort{
779 port: port,
780 fds: make(map[uintptr]interface{}),
781 paths: make(map[string]*fileObjCookie),
782 }
783 return e, nil
784 }
785
786
787
788
789
790
791
792
793 func (e *EventPort) Close() error {
794 e.mu.Lock()
795 defer e.mu.Unlock()
796 e.fds = nil
797 e.paths = nil
798 return Close(e.port)
799 }
800
801
802 func (e *EventPort) PathIsWatched(path string) bool {
803 e.mu.Lock()
804 defer e.mu.Unlock()
805 _, found := e.paths[path]
806 return found
807 }
808
809
810 func (e *EventPort) FdIsWatched(fd uintptr) bool {
811 e.mu.Lock()
812 defer e.mu.Unlock()
813 _, found := e.fds[fd]
814 return found
815 }
816
817
818
819 func (e *EventPort) AssociatePath(path string, stat os.FileInfo, events int, cookie interface{}) error {
820 e.mu.Lock()
821 defer e.mu.Unlock()
822 if _, found := e.paths[path]; found {
823 return fmt.Errorf("%v is already associated with this Event Port", path)
824 }
825 fobj, err := createFileObj(path, stat)
826 if err != nil {
827 return err
828 }
829 fCookie := &fileObjCookie{fobj, cookie}
830 _, err = port_associate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(fobj)), events, (*byte)(unsafe.Pointer(&fCookie.cookie)))
831 if err != nil {
832 return err
833 }
834 e.paths[path] = fCookie
835 return nil
836 }
837
838
839 func (e *EventPort) DissociatePath(path string) error {
840 e.mu.Lock()
841 defer e.mu.Unlock()
842 f, ok := e.paths[path]
843 if !ok {
844 return fmt.Errorf("%v is not associated with this Event Port", path)
845 }
846 _, err := port_dissociate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(f.fobj)))
847 if err != nil {
848 return err
849 }
850 delete(e.paths, path)
851 return nil
852 }
853
854
855 func (e *EventPort) AssociateFd(fd uintptr, events int, cookie interface{}) error {
856 e.mu.Lock()
857 defer e.mu.Unlock()
858 if _, found := e.fds[fd]; found {
859 return fmt.Errorf("%v is already associated with this Event Port", fd)
860 }
861 pcookie := &cookie
862 _, err := port_associate(e.port, PORT_SOURCE_FD, fd, events, (*byte)(unsafe.Pointer(pcookie)))
863 if err != nil {
864 return err
865 }
866 e.fds[fd] = pcookie
867 return nil
868 }
869
870
871 func (e *EventPort) DissociateFd(fd uintptr) error {
872 e.mu.Lock()
873 defer e.mu.Unlock()
874 _, ok := e.fds[fd]
875 if !ok {
876 return fmt.Errorf("%v is not associated with this Event Port", fd)
877 }
878 _, err := port_dissociate(e.port, PORT_SOURCE_FD, fd)
879 if err != nil {
880 return err
881 }
882 delete(e.fds, fd)
883 return nil
884 }
885
886 func createFileObj(name string, stat os.FileInfo) (*fileObj, error) {
887 fobj := new(fileObj)
888 bs, err := ByteSliceFromString(name)
889 if err != nil {
890 return nil, err
891 }
892 fobj.Name = (*int8)(unsafe.Pointer(&bs[0]))
893 s := stat.Sys().(*syscall.Stat_t)
894 fobj.Atim.Sec = s.Atim.Sec
895 fobj.Atim.Nsec = s.Atim.Nsec
896 fobj.Mtim.Sec = s.Mtim.Sec
897 fobj.Mtim.Nsec = s.Mtim.Nsec
898 fobj.Ctim.Sec = s.Ctim.Sec
899 fobj.Ctim.Nsec = s.Ctim.Nsec
900 return fobj, nil
901 }
902
903
904 func (e *EventPort) GetOne(t *Timespec) (*PortEvent, error) {
905 pe := new(portEvent)
906 _, err := port_get(e.port, pe, t)
907 if err != nil {
908 return nil, err
909 }
910 p := new(PortEvent)
911 p.Events = pe.Events
912 p.Source = pe.Source
913 e.mu.Lock()
914 defer e.mu.Unlock()
915 switch pe.Source {
916 case PORT_SOURCE_FD:
917 p.Fd = uintptr(pe.Object)
918 cookie := (*interface{})(unsafe.Pointer(pe.User))
919 p.Cookie = *cookie
920 delete(e.fds, p.Fd)
921 case PORT_SOURCE_FILE:
922 p.fobj = (*fileObj)(unsafe.Pointer(uintptr(pe.Object)))
923 p.Path = BytePtrToString((*byte)(unsafe.Pointer(p.fobj.Name)))
924 cookie := (*interface{})(unsafe.Pointer(pe.User))
925 p.Cookie = *cookie
926 delete(e.paths, p.Path)
927 }
928 return p, nil
929 }
930
931
932 func (e *EventPort) Pending() (int, error) {
933 var n uint32 = 0
934 _, err := port_getn(e.port, nil, 0, &n, nil)
935 return int(n), err
936 }
937
938
939
940
941
942 func (e *EventPort) Get(s []PortEvent, min int, timeout *Timespec) (int, error) {
943 if min == 0 {
944 return 0, fmt.Errorf("need to request at least one event or use Pending() instead")
945 }
946 if len(s) < min {
947 return 0, fmt.Errorf("len(s) (%d) is less than min events requested (%d)", len(s), min)
948 }
949 got := uint32(min)
950 max := uint32(len(s))
951 var err error
952 ps := make([]portEvent, max, max)
953 _, err = port_getn(e.port, &ps[0], max, &got, timeout)
954
955 if err != nil && err != ETIME {
956 return 0, err
957 }
958 e.mu.Lock()
959 defer e.mu.Unlock()
960 for i := 0; i < int(got); i++ {
961 s[i].Events = ps[i].Events
962 s[i].Source = ps[i].Source
963 switch ps[i].Source {
964 case PORT_SOURCE_FD:
965 s[i].Fd = uintptr(ps[i].Object)
966 cookie := (*interface{})(unsafe.Pointer(ps[i].User))
967 s[i].Cookie = *cookie
968 delete(e.fds, s[i].Fd)
969 case PORT_SOURCE_FILE:
970 s[i].fobj = (*fileObj)(unsafe.Pointer(uintptr(ps[i].Object)))
971 s[i].Path = BytePtrToString((*byte)(unsafe.Pointer(s[i].fobj.Name)))
972 cookie := (*interface{})(unsafe.Pointer(ps[i].User))
973 s[i].Cookie = *cookie
974 delete(e.paths, s[i].Path)
975 }
976 }
977 return int(got), err
978 }
979
View as plain text