1
2
3
4
5
6
7
8
9
10
11
12
13 package unix
14
15 import (
16 "fmt"
17 "syscall"
18 "unsafe"
19 )
20
21
22
23
24 func fdopendir(fd int) (dir uintptr, err error) {
25 r0, _, e1 := syscall_syscallPtr(libc_fdopendir_trampoline_addr, uintptr(fd), 0, 0)
26 dir = uintptr(r0)
27 if e1 != 0 {
28 err = errnoErr(e1)
29 }
30 return
31 }
32
33 var libc_fdopendir_trampoline_addr uintptr
34
35
36
37 func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
38
39
40
41
42
43
44
45 skip, err := Seek(fd, 0, 1 )
46 if err != nil {
47 return 0, err
48 }
49
50
51
52
53
54
55
56 fd2, err := Openat(fd, ".", O_RDONLY, 0)
57 if err != nil {
58 return 0, err
59 }
60 d, err := fdopendir(fd2)
61 if err != nil {
62 Close(fd2)
63 return 0, err
64 }
65 defer closedir(d)
66
67 var cnt int64
68 for {
69 var entry Dirent
70 var entryp *Dirent
71 e := readdir_r(d, &entry, &entryp)
72 if e != 0 {
73 return n, errnoErr(e)
74 }
75 if entryp == nil {
76 break
77 }
78 if skip > 0 {
79 skip--
80 cnt++
81 continue
82 }
83
84 reclen := int(entry.Reclen)
85 if reclen > len(buf) {
86
87
88
89
90 break
91 }
92
93
94 s := unsafe.Slice((*byte)(unsafe.Pointer(&entry)), reclen)
95 copy(buf, s)
96
97 buf = buf[reclen:]
98 n += reclen
99 cnt++
100 }
101
102
103 _, err = Seek(fd, cnt, 0 )
104 if err != nil {
105 return n, err
106 }
107
108 return n, nil
109 }
110
111
112 type SockaddrDatalink struct {
113 Len uint8
114 Family uint8
115 Index uint16
116 Type uint8
117 Nlen uint8
118 Alen uint8
119 Slen uint8
120 Data [12]int8
121 raw RawSockaddrDatalink
122 }
123
124
125 type SockaddrCtl struct {
126 ID uint32
127 Unit uint32
128 raw RawSockaddrCtl
129 }
130
131 func (sa *SockaddrCtl) sockaddr() (unsafe.Pointer, _Socklen, error) {
132 sa.raw.Sc_len = SizeofSockaddrCtl
133 sa.raw.Sc_family = AF_SYSTEM
134 sa.raw.Ss_sysaddr = AF_SYS_CONTROL
135 sa.raw.Sc_id = sa.ID
136 sa.raw.Sc_unit = sa.Unit
137 return unsafe.Pointer(&sa.raw), SizeofSockaddrCtl, nil
138 }
139
140
141
142
143
144 type SockaddrVM struct {
145
146
147
148
149
150 CID uint32
151 Port uint32
152 raw RawSockaddrVM
153 }
154
155 func (sa *SockaddrVM) sockaddr() (unsafe.Pointer, _Socklen, error) {
156 sa.raw.Len = SizeofSockaddrVM
157 sa.raw.Family = AF_VSOCK
158 sa.raw.Port = sa.Port
159 sa.raw.Cid = sa.CID
160
161 return unsafe.Pointer(&sa.raw), SizeofSockaddrVM, nil
162 }
163
164 func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
165 switch rsa.Addr.Family {
166 case AF_SYSTEM:
167 pp := (*RawSockaddrCtl)(unsafe.Pointer(rsa))
168 if pp.Ss_sysaddr == AF_SYS_CONTROL {
169 sa := new(SockaddrCtl)
170 sa.ID = pp.Sc_id
171 sa.Unit = pp.Sc_unit
172 return sa, nil
173 }
174 case AF_VSOCK:
175 pp := (*RawSockaddrVM)(unsafe.Pointer(rsa))
176 sa := &SockaddrVM{
177 CID: pp.Cid,
178 Port: pp.Port,
179 }
180 return sa, nil
181 }
182 return nil, EAFNOSUPPORT
183 }
184
185
186
187
188 const SYS___SYSCTL = SYS_SYSCTL
189
190
191 func nametomib(name string) (mib []_C_int, err error) {
192 const siz = unsafe.Sizeof(mib[0])
193
194
195
196
197
198
199
200
201 var buf [CTL_MAXNAME + 2]_C_int
202 n := uintptr(CTL_MAXNAME) * siz
203
204 p := (*byte)(unsafe.Pointer(&buf[0]))
205 bytes, err := ByteSliceFromString(name)
206 if err != nil {
207 return nil, err
208 }
209
210
211
212 if err = sysctl([]_C_int{0, 3}, p, &n, &bytes[0], uintptr(len(name))); err != nil {
213 return nil, err
214 }
215 return buf[0 : n/siz], nil
216 }
217
218 func direntIno(buf []byte) (uint64, bool) {
219 return readInt(buf, unsafe.Offsetof(Dirent{}.Ino), unsafe.Sizeof(Dirent{}.Ino))
220 }
221
222 func direntReclen(buf []byte) (uint64, bool) {
223 return readInt(buf, unsafe.Offsetof(Dirent{}.Reclen), unsafe.Sizeof(Dirent{}.Reclen))
224 }
225
226 func direntNamlen(buf []byte) (uint64, bool) {
227 return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
228 }
229
230 func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) }
231 func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) }
232 func PtraceDenyAttach() (err error) { return ptrace(PT_DENY_ATTACH, 0, 0, 0) }
233
234
235
236 func Pipe(p []int) (err error) {
237 if len(p) != 2 {
238 return EINVAL
239 }
240 var x [2]int32
241 err = pipe(&x)
242 if err == nil {
243 p[0] = int(x[0])
244 p[1] = int(x[1])
245 }
246 return
247 }
248
249 func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
250 var _p0 unsafe.Pointer
251 var bufsize uintptr
252 if len(buf) > 0 {
253 _p0 = unsafe.Pointer(&buf[0])
254 bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
255 }
256 return getfsstat(_p0, bufsize, flags)
257 }
258
259 func xattrPointer(dest []byte) *byte {
260
261
262
263
264
265 var destp *byte
266 if len(dest) > 0 {
267 destp = &dest[0]
268 }
269 return destp
270 }
271
272
273
274 func Getxattr(path string, attr string, dest []byte) (sz int, err error) {
275 return getxattr(path, attr, xattrPointer(dest), len(dest), 0, 0)
276 }
277
278 func Lgetxattr(link string, attr string, dest []byte) (sz int, err error) {
279 return getxattr(link, attr, xattrPointer(dest), len(dest), 0, XATTR_NOFOLLOW)
280 }
281
282
283
284 func Fgetxattr(fd int, attr string, dest []byte) (sz int, err error) {
285 return fgetxattr(fd, attr, xattrPointer(dest), len(dest), 0, 0)
286 }
287
288
289
290 func Setxattr(path string, attr string, data []byte, flags int) (err error) {
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317 return setxattr(path, attr, xattrPointer(data), len(data), 0, flags)
318 }
319
320 func Lsetxattr(link string, attr string, data []byte, flags int) (err error) {
321 return setxattr(link, attr, xattrPointer(data), len(data), 0, flags|XATTR_NOFOLLOW)
322 }
323
324
325
326 func Fsetxattr(fd int, attr string, data []byte, flags int) (err error) {
327 return fsetxattr(fd, attr, xattrPointer(data), len(data), 0, 0)
328 }
329
330
331
332 func Removexattr(path string, attr string) (err error) {
333
334
335
336 return removexattr(path, attr, 0)
337 }
338
339 func Lremovexattr(link string, attr string) (err error) {
340 return removexattr(link, attr, XATTR_NOFOLLOW)
341 }
342
343
344
345 func Fremovexattr(fd int, attr string) (err error) {
346 return fremovexattr(fd, attr, 0)
347 }
348
349
350
351 func Listxattr(path string, dest []byte) (sz int, err error) {
352 return listxattr(path, xattrPointer(dest), len(dest), 0)
353 }
354
355 func Llistxattr(link string, dest []byte) (sz int, err error) {
356 return listxattr(link, xattrPointer(dest), len(dest), XATTR_NOFOLLOW)
357 }
358
359
360
361 func Flistxattr(fd int, dest []byte) (sz int, err error) {
362 return flistxattr(fd, xattrPointer(dest), len(dest), 0)
363 }
364
365
366
367
370
371
372
373
374
375 func Kill(pid int, signum syscall.Signal) (err error) { return kill(pid, int(signum), 1) }
376
377
378
379
380 func IoctlCtlInfo(fd int, ctlInfo *CtlInfo) error {
381 return ioctlPtr(fd, CTLIOCGINFO, unsafe.Pointer(ctlInfo))
382 }
383
384
385 type IfreqMTU struct {
386 Name [IFNAMSIZ]byte
387 MTU int32
388 }
389
390
391
392 func IoctlGetIfreqMTU(fd int, ifname string) (*IfreqMTU, error) {
393 var ifreq IfreqMTU
394 copy(ifreq.Name[:], ifname)
395 err := ioctlPtr(fd, SIOCGIFMTU, unsafe.Pointer(&ifreq))
396 return &ifreq, err
397 }
398
399
400
401 func IoctlSetIfreqMTU(fd int, ifreq *IfreqMTU) error {
402 return ioctlPtr(fd, SIOCSIFMTU, unsafe.Pointer(ifreq))
403 }
404
405
406
407 func RenamexNp(from string, to string, flag uint32) (err error) {
408 return renamexNp(from, to, flag)
409 }
410
411
412
413 func RenameatxNp(fromfd int, from string, tofd int, to string, flag uint32) (err error) {
414 return renameatxNp(fromfd, from, tofd, to, flag)
415 }
416
417
418
419 func Uname(uname *Utsname) error {
420 mib := []_C_int{CTL_KERN, KERN_OSTYPE}
421 n := unsafe.Sizeof(uname.Sysname)
422 if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil {
423 return err
424 }
425
426 mib = []_C_int{CTL_KERN, KERN_HOSTNAME}
427 n = unsafe.Sizeof(uname.Nodename)
428 if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil {
429 return err
430 }
431
432 mib = []_C_int{CTL_KERN, KERN_OSRELEASE}
433 n = unsafe.Sizeof(uname.Release)
434 if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil {
435 return err
436 }
437
438 mib = []_C_int{CTL_KERN, KERN_VERSION}
439 n = unsafe.Sizeof(uname.Version)
440 if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil {
441 return err
442 }
443
444
445
446 for i, b := range uname.Version {
447 if b == '\n' || b == '\t' {
448 if i == len(uname.Version)-1 {
449 uname.Version[i] = 0
450 } else {
451 uname.Version[i] = ' '
452 }
453 }
454 }
455
456 mib = []_C_int{CTL_HW, HW_MACHINE}
457 n = unsafe.Sizeof(uname.Machine)
458 if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil {
459 return err
460 }
461
462 return nil
463 }
464
465 func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
466 if raceenabled {
467 raceReleaseMerge(unsafe.Pointer(&ioSync))
468 }
469 var length = int64(count)
470 err = sendfile(infd, outfd, *offset, &length, nil, 0)
471 written = int(length)
472 return
473 }
474
475 func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, error) {
476 var value IPMreqn
477 vallen := _Socklen(SizeofIPMreqn)
478 errno := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
479 return &value, errno
480 }
481
482 func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (err error) {
483 return setsockopt(fd, level, opt, unsafe.Pointer(mreq), unsafe.Sizeof(*mreq))
484 }
485
486
487
488 func GetsockoptXucred(fd, level, opt int) (*Xucred, error) {
489 x := new(Xucred)
490 vallen := _Socklen(SizeofXucred)
491 err := getsockopt(fd, level, opt, unsafe.Pointer(x), &vallen)
492 return x, err
493 }
494
495 func GetsockoptTCPConnectionInfo(fd, level, opt int) (*TCPConnectionInfo, error) {
496 var value TCPConnectionInfo
497 vallen := _Socklen(SizeofTCPConnectionInfo)
498 err := getsockopt(fd, level, opt, unsafe.Pointer(&value), &vallen)
499 return &value, err
500 }
501
502 func SysctlKinfoProc(name string, args ...int) (*KinfoProc, error) {
503 mib, err := sysctlmib(name, args...)
504 if err != nil {
505 return nil, err
506 }
507
508 var kinfo KinfoProc
509 n := uintptr(SizeofKinfoProc)
510 if err := sysctl(mib, (*byte)(unsafe.Pointer(&kinfo)), &n, nil, 0); err != nil {
511 return nil, err
512 }
513 if n != SizeofKinfoProc {
514 return nil, EIO
515 }
516 return &kinfo, nil
517 }
518
519 func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
520 mib, err := sysctlmib(name, args...)
521 if err != nil {
522 return nil, err
523 }
524
525 for {
526
527 n := uintptr(0)
528 if err := sysctl(mib, nil, &n, nil, 0); err != nil {
529 return nil, err
530 }
531 if n == 0 {
532 return nil, nil
533 }
534 if n%SizeofKinfoProc != 0 {
535 return nil, fmt.Errorf("sysctl() returned a size of %d, which is not a multiple of %d", n, SizeofKinfoProc)
536 }
537
538
539 buf := make([]KinfoProc, n/SizeofKinfoProc)
540 if err := sysctl(mib, (*byte)(unsafe.Pointer(&buf[0])), &n, nil, 0); err != nil {
541 if err == ENOMEM {
542
543 continue
544 }
545 return nil, err
546 }
547 if n%SizeofKinfoProc != 0 {
548 return nil, fmt.Errorf("sysctl() returned a size of %d, which is not a multiple of %d", n, SizeofKinfoProc)
549 }
550
551
552
553 return buf[:n/SizeofKinfoProc], nil
554 }
555 }
556
557
558
559 func PthreadChdir(path string) (err error) {
560 return pthread_chdir_np(path)
561 }
562
563
564
565 func PthreadFchdir(fd int) (err error) {
566 return pthread_fchdir_np(fd)
567 }
568
569
570
571
572
573
574
575
576
577
578 func Connectx(fd int, srcIf uint32, srcAddr, dstAddr Sockaddr, associd SaeAssocID, flags uint32, iov []Iovec, connid *SaeConnID) (n uintptr, err error) {
579 endpoints := SaEndpoints{
580 Srcif: srcIf,
581 }
582
583 if srcAddr != nil {
584 addrp, addrlen, err := srcAddr.sockaddr()
585 if err != nil {
586 return 0, err
587 }
588 endpoints.Srcaddr = (*RawSockaddr)(addrp)
589 endpoints.Srcaddrlen = uint32(addrlen)
590 }
591
592 if dstAddr != nil {
593 addrp, addrlen, err := dstAddr.sockaddr()
594 if err != nil {
595 return 0, err
596 }
597 endpoints.Dstaddr = (*RawSockaddr)(addrp)
598 endpoints.Dstaddrlen = uint32(addrlen)
599 }
600
601 err = connectx(fd, &endpoints, associd, flags, iov, &n, connid)
602 return
603 }
604
605
606 const minIovec = 8
607
608 func Readv(fd int, iovs [][]byte) (n int, err error) {
609 if !darwinKernelVersionMin(11, 0, 0) {
610 return 0, ENOSYS
611 }
612
613 iovecs := make([]Iovec, 0, minIovec)
614 iovecs = appendBytes(iovecs, iovs)
615 n, err = readv(fd, iovecs)
616 readvRacedetect(iovecs, n, err)
617 return n, err
618 }
619
620 func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) {
621 if !darwinKernelVersionMin(11, 0, 0) {
622 return 0, ENOSYS
623 }
624 iovecs := make([]Iovec, 0, minIovec)
625 iovecs = appendBytes(iovecs, iovs)
626 n, err = preadv(fd, iovecs, offset)
627 readvRacedetect(iovecs, n, err)
628 return n, err
629 }
630
631 func Writev(fd int, iovs [][]byte) (n int, err error) {
632 if !darwinKernelVersionMin(11, 0, 0) {
633 return 0, ENOSYS
634 }
635
636 iovecs := make([]Iovec, 0, minIovec)
637 iovecs = appendBytes(iovecs, iovs)
638 if raceenabled {
639 raceReleaseMerge(unsafe.Pointer(&ioSync))
640 }
641 n, err = writev(fd, iovecs)
642 writevRacedetect(iovecs, n)
643 return n, err
644 }
645
646 func Pwritev(fd int, iovs [][]byte, offset int64) (n int, err error) {
647 if !darwinKernelVersionMin(11, 0, 0) {
648 return 0, ENOSYS
649 }
650
651 iovecs := make([]Iovec, 0, minIovec)
652 iovecs = appendBytes(iovecs, iovs)
653 if raceenabled {
654 raceReleaseMerge(unsafe.Pointer(&ioSync))
655 }
656 n, err = pwritev(fd, iovecs, offset)
657 writevRacedetect(iovecs, n)
658 return n, err
659 }
660
661 func appendBytes(vecs []Iovec, bs [][]byte) []Iovec {
662 for _, b := range bs {
663 var v Iovec
664 v.SetLen(len(b))
665 if len(b) > 0 {
666 v.Base = &b[0]
667 } else {
668 v.Base = (*byte)(unsafe.Pointer(&_zero))
669 }
670 vecs = append(vecs, v)
671 }
672 return vecs
673 }
674
675 func writevRacedetect(iovecs []Iovec, n int) {
676 if !raceenabled {
677 return
678 }
679 for i := 0; n > 0 && i < len(iovecs); i++ {
680 m := int(iovecs[i].Len)
681 if m > n {
682 m = n
683 }
684 n -= m
685 if m > 0 {
686 raceReadRange(unsafe.Pointer(iovecs[i].Base), m)
687 }
688 }
689 }
690
691 func readvRacedetect(iovecs []Iovec, n int, err error) {
692 if !raceenabled {
693 return
694 }
695 for i := 0; n > 0 && i < len(iovecs); i++ {
696 m := int(iovecs[i].Len)
697 if m > n {
698 m = n
699 }
700 n -= m
701 if m > 0 {
702 raceWriteRange(unsafe.Pointer(iovecs[i].Base), m)
703 }
704 }
705 if err == nil {
706 raceAcquire(unsafe.Pointer(&ioSync))
707 }
708 }
709
710 func darwinMajorMinPatch() (maj, min, patch int, err error) {
711 var un Utsname
712 err = Uname(&un)
713 if err != nil {
714 return
715 }
716
717 var mmp [3]int
718 c := 0
719 Loop:
720 for _, b := range un.Release[:] {
721 switch {
722 case b >= '0' && b <= '9':
723 mmp[c] = 10*mmp[c] + int(b-'0')
724 case b == '.':
725 c++
726 if c > 2 {
727 return 0, 0, 0, ENOTSUP
728 }
729 case b == 0:
730 break Loop
731 default:
732 return 0, 0, 0, ENOTSUP
733 }
734 }
735 if c != 2 {
736 return 0, 0, 0, ENOTSUP
737 }
738 return mmp[0], mmp[1], mmp[2], nil
739 }
740
741 func darwinKernelVersionMin(maj, min, patch int) bool {
742 actualMaj, actualMin, actualPatch, err := darwinMajorMinPatch()
743 if err != nil {
744 return false
745 }
746 return actualMaj > maj || actualMaj == maj && (actualMin > min || actualMin == min && actualPatch >= patch)
747 }
748
749
750
751
752
753
754
755
756
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
View as plain text