1
2
3
4
5 package poll
6
7 import (
8 "errors"
9 "internal/race"
10 "internal/syscall/windows"
11 "io"
12 "runtime"
13 "sync"
14 "syscall"
15 "unicode/utf16"
16 "unicode/utf8"
17 "unsafe"
18 )
19
20 var (
21 initErr error
22 ioSync uint64
23 )
24
25
26
27 var ifsHandlesOnly = sync.OnceValue(func() bool {
28 protos := [2]int32{syscall.IPPROTO_TCP, 0}
29 var buf [32]syscall.WSAProtocolInfo
30 len := uint32(unsafe.Sizeof(buf))
31 n, err := syscall.WSAEnumProtocols(&protos[0], &buf[0], &len)
32 if err != nil {
33 return false
34 }
35 for i := range n {
36 if buf[i].ServiceFlags1&syscall.XP1_IFS_HANDLES == 0 {
37 return false
38 }
39 }
40 return true
41 })
42
43
44
45 func canSkipCompletionPortOnSuccess(h syscall.Handle, isSocket bool) bool {
46 if !isSocket {
47
48 return true
49 }
50 if ifsHandlesOnly() {
51
52 return true
53 }
54 var info syscall.WSAProtocolInfo
55 size := int32(unsafe.Sizeof(info))
56 if syscall.Getsockopt(h, syscall.SOL_SOCKET, windows.SO_PROTOCOL_INFOW, (*byte)(unsafe.Pointer(&info)), &size) != nil {
57 return false
58 }
59 return info.ServiceFlags1&syscall.XP1_IFS_HANDLES != 0
60 }
61
62
63
64
65 var InitWSA = sync.OnceFunc(func() {
66 var d syscall.WSAData
67 e := syscall.WSAStartup(uint32(0x202), &d)
68 if e != nil {
69 initErr = e
70 }
71 })
72
73
74 type operation struct {
75
76
77 o syscall.Overlapped
78
79
80 runtimeCtx uintptr
81 mode int32
82 }
83
84 func (o *operation) setOffset(off int64) {
85 o.o.OffsetHigh = uint32(off >> 32)
86 o.o.Offset = uint32(off)
87 }
88
89 func (fd *FD) overlapped(o *operation) *syscall.Overlapped {
90 if fd.isBlocking {
91
92
93
94
95 return nil
96 }
97 return &o.o
98 }
99
100 func newWsaBuf(b []byte) *syscall.WSABuf {
101 return &syscall.WSABuf{Buf: unsafe.SliceData(b), Len: uint32(len(b))}
102 }
103
104 var wsaBufsPool = sync.Pool{
105 New: func() any {
106 buf := make([]syscall.WSABuf, 0, 16)
107 return &buf
108 },
109 }
110
111 func newWSABufs(buf *[][]byte) *[]syscall.WSABuf {
112 bufsPtr := wsaBufsPool.Get().(*[]syscall.WSABuf)
113 *bufsPtr = (*bufsPtr)[:0]
114 for _, b := range *buf {
115 if len(b) == 0 {
116 *bufsPtr = append(*bufsPtr, syscall.WSABuf{})
117 continue
118 }
119 for len(b) > maxRW {
120 *bufsPtr = append(*bufsPtr, syscall.WSABuf{Len: maxRW, Buf: &b[0]})
121 b = b[maxRW:]
122 }
123 if len(b) > 0 {
124 *bufsPtr = append(*bufsPtr, syscall.WSABuf{Len: uint32(len(b)), Buf: &b[0]})
125 }
126 }
127 return bufsPtr
128 }
129
130 func freeWSABufs(bufsPtr *[]syscall.WSABuf) {
131
132 bufs := *bufsPtr
133 for i := range bufs {
134 bufs[i].Buf = nil
135 }
136
137
138
139
140
141
142 if cap(*bufsPtr) > 128 {
143 *bufsPtr = nil
144 }
145 wsaBufsPool.Put(bufsPtr)
146 }
147
148
149 var wsaMsgPool = sync.Pool{
150 New: func() any {
151 return &windows.WSAMsg{
152 Buffers: &syscall.WSABuf{},
153 BufferCount: 1,
154 }
155 },
156 }
157
158
159
160 func newWSAMsg(p []byte, oob []byte, flags int, rsa *wsaRsa) *windows.WSAMsg {
161
162
163
164
165
166 msg := wsaMsgPool.Get().(*windows.WSAMsg)
167 msg.Buffers.Len = uint32(len(p))
168 msg.Buffers.Buf = unsafe.SliceData(p)
169 if len(oob) > 0 {
170 msg.Control = syscall.WSABuf{
171 Len: uint32(len(oob)),
172 Buf: unsafe.SliceData(oob),
173 }
174 }
175 msg.Flags = uint32(flags)
176 if rsa != nil {
177 msg.Name = &rsa.name
178 msg.Namelen = rsa.namelen
179 }
180 return msg
181 }
182
183 func freeWSAMsg(msg *windows.WSAMsg) {
184
185 msg.Name = nil
186 msg.Namelen = 0
187 msg.Buffers.Len = 0
188 msg.Buffers.Buf = nil
189 msg.Control.Len = 0
190 msg.Control.Buf = nil
191 wsaMsgPool.Put(msg)
192 }
193
194
195
196
197
198 type wsaRsa struct {
199 name syscall.RawSockaddrAny
200 namelen int32
201 }
202
203 var wsaRsaPool = sync.Pool{
204 New: func() any {
205 return new(wsaRsa)
206 },
207 }
208
209 func newWSARsa() *wsaRsa {
210 rsa := wsaRsaPool.Get().(*wsaRsa)
211 rsa.name = syscall.RawSockaddrAny{}
212 rsa.namelen = int32(unsafe.Sizeof(syscall.RawSockaddrAny{}))
213 return rsa
214 }
215
216 var operationPool = sync.Pool{
217 New: func() any {
218 return new(operation)
219 },
220 }
221
222
223
224 func (fd *FD) waitIO(o *operation) error {
225 if o.o.HEvent != 0 {
226
227
228 if fd.kind == kindPipe && fd.closing() {
229 if err := syscall.CancelIoEx(fd.Sysfd, &o.o); err != nil && err != syscall.ERROR_NOT_FOUND {
230
231 panic(err)
232 }
233 }
234
235
236
237 _, err := syscall.WaitForSingleObject(o.o.HEvent, syscall.INFINITE)
238 return err
239 }
240
241 err := fd.pd.wait(int(o.mode), fd.isFile)
242 switch err {
243 case nil:
244
245 case ErrNetClosing, ErrFileClosing, ErrDeadlineExceeded:
246
247
248
249 if err := syscall.CancelIoEx(fd.Sysfd, &o.o); err != nil && err != syscall.ERROR_NOT_FOUND {
250
251 panic(err)
252 }
253 fd.pd.waitCanceled(int(o.mode))
254 default:
255
256 panic("unexpected runtime.netpoll error: " + err.Error())
257 }
258 return err
259 }
260
261
262
263
264
265 func (fd *FD) execIO(
266 mode int,
267 submit func(o *operation) (uint32, error),
268 pinPtrs ...any,
269 ) (int, error) {
270 if err := fd.ensureInit(); err != nil {
271 return 0, err
272 }
273
274 err := fd.pd.prepare(mode, fd.isFile)
275 if err != nil {
276 return 0, err
277 }
278 o := operationPool.Get().(*operation)
279 defer operationPool.Put(o)
280 *o = operation{
281 runtimeCtx: fd.pd.runtimeCtx,
282 mode: int32(mode),
283 }
284 if !fd.isBlocking {
285 var pinner *runtime.Pinner
286 if mode == 'r' {
287 pinner = &fd.readPinner
288 } else {
289 pinner = &fd.writePinner
290 }
291 defer pinner.Unpin()
292
293 pinner.Pin(o)
294 for _, ptr := range pinPtrs {
295 pinner.Pin(ptr)
296 }
297
298 if !fd.associated {
299
300
301
302 h, err := windows.CreateEvent(nil, 0, 0, nil)
303 if err != nil {
304
305 panic(err)
306 }
307
308 o.o.HEvent = h | 1
309 defer syscall.CloseHandle(h)
310 }
311 }
312
313 qty, err := submit(o)
314 var waitErr error
315
316
317 waitOnSuccess := o.o.HEvent == 0 && fd.waitOnSuccess
318
319
320 if !fd.isBlocking && (err == syscall.ERROR_IO_PENDING || (err == nil && waitOnSuccess)) {
321
322
323 waitErr = fd.waitIO(o)
324 if fd.isFile {
325 err = windows.GetOverlappedResult(fd.Sysfd, &o.o, &qty, false)
326 } else {
327 var flags uint32
328 err = windows.WSAGetOverlappedResult(fd.Sysfd, &o.o, &qty, false, &flags)
329 }
330 }
331 switch err {
332 case syscall.ERROR_OPERATION_ABORTED:
333
334
335
336 if waitErr != nil {
337
338 err = waitErr
339 } else if fd.kind == kindPipe && fd.closing() {
340
341
342 err = errClosing(fd.isFile)
343 }
344 case windows.ERROR_IO_INCOMPLETE:
345
346 if waitErr != nil {
347
348 err = waitErr
349 }
350 }
351 return int(qty), err
352 }
353
354
355
356 type FD struct {
357
358 fdmu fdMutex
359
360
361 Sysfd syscall.Handle
362
363
364 pd pollDesc
365
366
367 ioCancel ioCancelState
368
369
370
371
372
373 lazyInit bool
374 initOnce sync.Once
375 initMu sync.Mutex
376 skipIOCP bool
377
378
379
380
381
382
383 offset int64
384
385
386 lastbits []byte
387 readuint16 []uint16
388 readbyte []byte
389 readbyteOffset int
390
391
392 csema uint32
393
394
395
396 waitOnSuccess bool
397
398
399
400 IsStream bool
401
402
403
404 ZeroReadIsEOF bool
405
406
407
408 KeepFileCompletionModes bool
409
410
411 isFile bool
412
413
414 kind fileKind
415
416
417 isBlocking bool
418
419
420 associated bool
421
422
423
424 readPinner runtime.Pinner
425 writePinner runtime.Pinner
426 }
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441 func (fd *FD) setOffset(off int64) {
442 fd.offset = off
443 }
444
445
446 func (fd *FD) addOffset(off int) {
447 fd.offset += int64(off)
448 }
449
450
451 type fileKind byte
452
453 const (
454 kindNet fileKind = iota
455 kindFile
456 kindConsole
457 kindPipe
458 )
459
460
461
462
463
464
465
466
467
468 func (fd *FD) Init(net string, overlapped *bool) error {
469 if initErr != nil {
470 return initErr
471 }
472
473 switch net {
474 case "file":
475 fd.kind = kindFile
476 case "console":
477 fd.kind = kindConsole
478 case "pipe":
479 fd.kind = kindPipe
480 default:
481
482 fd.kind = kindNet
483 }
484 fd.isFile = fd.kind != kindNet
485 fd.lazyInit = overlapped == nil
486 fd.isBlocking = overlapped == nil || !*overlapped
487
488 if fd.isBlocking {
489 return nil
490 }
491 return fd.initIOCP()
492 }
493
494
495
496 func (fd *FD) ensureInit() error {
497 if !fd.lazyInit {
498 return nil
499 }
500 fd.initOnce.Do(func() {
501 fd.initMu.Lock()
502 defer fd.initMu.Unlock()
503 if fd.closing() {
504 return
505 }
506
507
508
509
510 overlapped, _ := windows.IsNonblock(fd.Sysfd)
511 fd.isBlocking = !overlapped
512 if overlapped && !fd.skipIOCP && !fd.closing() {
513
514
515 _ = fd.initIOCP()
516 }
517 })
518 if fd.closing() {
519 return errClosing(fd.isFile)
520 }
521 return nil
522 }
523
524
525
526
527 func (fd *FD) initIOCP() error {
528 var modes uint32
529 if fd.KeepFileCompletionModes {
530
531
532 var err error
533 modes, err = fd.getFileCompletionModes()
534 if err != nil {
535
536
537
538
539 return nil
540 }
541 }
542
543
544
545
546 if err := fd.pd.init(fd); err != nil {
547 return err
548 }
549 fd.associated = true
550
551 if !fd.KeepFileCompletionModes {
552
553 modes = fd.setFileCompletionModes()
554 }
555 fd.waitOnSuccess = modes&syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS == 0
556 return nil
557 }
558
559
560 func (fd *FD) getFileCompletionModes() (uint32, error) {
561 var info windows.FILE_IO_COMPLETION_NOTIFICATION_INFORMATION
562 err := windows.NtQueryInformationFile(fd.Sysfd, &windows.IO_STATUS_BLOCK{},
563 unsafe.Pointer(&info), uint32(unsafe.Sizeof(info)), windows.FileIoCompletionNotificationInformation)
564 return info.Flags, err
565 }
566
567
568
569 func (fd *FD) setFileCompletionModes() uint32 {
570
571
572
573 modes := uint8(syscall.FILE_SKIP_SET_EVENT_ON_HANDLE)
574 if canSkipCompletionPortOnSuccess(fd.Sysfd, fd.kind == kindNet) {
575 modes |= syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
576 }
577 if syscall.SetFileCompletionNotificationModes(fd.Sysfd, modes) != nil {
578
579
580 return 0
581 }
582 return uint32(modes)
583 }
584
585
586
587
588 func (fd *FD) DisassociateIOCP() error {
589
590
591
592 if ok, err := fd.tryReadWriteLock(); err != nil || !ok {
593 if err == nil {
594 err = errors.New("can't disassociate the handle while there is in-progress I/O")
595 }
596 return err
597 }
598 defer fd.readWriteUnlock()
599
600 if fd.lazyInit {
601 if !fd.initMu.TryLock() {
602
603 return errors.New("can't disassociate the handle while initialization is in progress")
604 }
605 defer fd.initMu.Unlock()
606
607
608 fd.skipIOCP = true
609 }
610 if !fd.associated {
611
612 return nil
613 }
614
615 info := windows.FILE_COMPLETION_INFORMATION{}
616 if err := windows.NtSetInformationFile(fd.Sysfd, &windows.IO_STATUS_BLOCK{}, unsafe.Pointer(&info), uint32(unsafe.Sizeof(info)), windows.FileReplaceCompletionInformation); err != nil {
617 return err
618 }
619
620 fd.associated = false
621
622
623 return nil
624 }
625
626 func (fd *FD) destroy() error {
627 if fd.Sysfd == syscall.InvalidHandle {
628 return syscall.EINVAL
629 }
630
631
632 fd.pd.close()
633 var err error
634 switch fd.kind {
635 case kindNet:
636
637 err = CloseFunc(fd.Sysfd)
638 default:
639 err = syscall.CloseHandle(fd.Sysfd)
640 }
641 fd.Sysfd = syscall.InvalidHandle
642 runtime_Semrelease(&fd.csema)
643 return err
644 }
645
646
647
648 func (fd *FD) Close() error {
649 if !fd.fdmu.increfAndClose() {
650 return errClosing(fd.isFile)
651 }
652
653 if fd.kind == kindPipe {
654 fd.cancelIO()
655 }
656
657 if fd.lazyInit {
658
659 fd.initMu.Lock()
660 fd.pd.evict()
661 fd.initMu.Unlock()
662 } else {
663 fd.pd.evict()
664 }
665 err := fd.decref()
666
667
668 runtime_Semacquire(&fd.csema)
669 return err
670 }
671
672
673
674
675 const maxRW = 1 << 30
676
677 func pinPtrsFromBuf(buf []byte) []any {
678 if len(buf) == 0 {
679 return nil
680 }
681 return []any{unsafe.SliceData(buf)}
682 }
683
684
685 func (fd *FD) Read(buf []byte) (int, error) {
686 if fd.kind == kindFile {
687 if err := fd.readWriteLock(); err != nil {
688 return 0, err
689 }
690 defer fd.readWriteUnlock()
691 } else {
692 if err := fd.readLock(); err != nil {
693 return 0, err
694 }
695 defer fd.readUnlock()
696 }
697
698 if len(buf) > maxRW {
699 buf = buf[:maxRW]
700 }
701
702 var n int
703 var err error
704 switch fd.kind {
705 case kindConsole:
706 n, err = fd.readConsole(buf)
707 case kindFile:
708 n, err = fd.execIO('r', func(o *operation) (qty uint32, err error) {
709 o.setOffset(fd.offset)
710 err = syscall.ReadFile(fd.Sysfd, buf, &qty, fd.overlapped(o))
711 return qty, err
712 }, pinPtrsFromBuf(buf)...)
713 fd.addOffset(n)
714 if err == syscall.ERROR_HANDLE_EOF {
715 err = io.EOF
716 }
717 case kindPipe:
718 n, err = fd.execIO('r', func(o *operation) (qty uint32, err error) {
719 if fd.isBlocking {
720 return fd.execSyncIO(syscall.ReadFile, buf)
721 }
722 err = syscall.ReadFile(fd.Sysfd, buf, &qty, fd.overlapped(o))
723 return qty, err
724 }, pinPtrsFromBuf(buf)...)
725 if err == syscall.ERROR_HANDLE_EOF || err == syscall.ERROR_BROKEN_PIPE {
726 err = io.EOF
727 }
728 case kindNet:
729 n, err = fd.execIO('r', func(o *operation) (qty uint32, err error) {
730 var flags uint32
731 err = syscall.WSARecv(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, &o.o, nil)
732 return qty, err
733 }, pinPtrsFromBuf(buf)...)
734 if race.Enabled {
735 race.Acquire(unsafe.Pointer(&ioSync))
736 }
737 }
738 if len(buf) != 0 {
739 err = fd.eofError(n, err)
740 }
741 return n, err
742 }
743
744 var ReadConsole = syscall.ReadConsole
745
746
747
748
749 func (fd *FD) readConsole(b []byte) (int, error) {
750 if len(b) == 0 {
751 return 0, nil
752 }
753
754 if fd.readuint16 == nil {
755
756
757
758 fd.readuint16 = make([]uint16, 0, 10000)
759 fd.readbyte = make([]byte, 0, 4*cap(fd.readuint16))
760 }
761
762 for fd.readbyteOffset >= len(fd.readbyte) {
763 n := cap(fd.readuint16) - len(fd.readuint16)
764 if n > len(b) {
765 n = len(b)
766 }
767 var nw uint32
768 err := ReadConsole(fd.Sysfd, &fd.readuint16[:len(fd.readuint16)+1][len(fd.readuint16)], uint32(n), &nw, nil)
769 if err != nil {
770 return 0, err
771 }
772 uint16s := fd.readuint16[:len(fd.readuint16)+int(nw)]
773 fd.readuint16 = fd.readuint16[:0]
774 buf := fd.readbyte[:0]
775 for i := 0; i < len(uint16s); i++ {
776 r := rune(uint16s[i])
777 if utf16.IsSurrogate(r) {
778 if i+1 == len(uint16s) {
779 if nw > 0 {
780
781 fd.readuint16 = fd.readuint16[:1]
782 fd.readuint16[0] = uint16(r)
783 break
784 }
785 r = utf8.RuneError
786 } else {
787 r = utf16.DecodeRune(r, rune(uint16s[i+1]))
788 if r != utf8.RuneError {
789 i++
790 }
791 }
792 }
793 buf = utf8.AppendRune(buf, r)
794 }
795 fd.readbyte = buf
796 fd.readbyteOffset = 0
797 if nw == 0 {
798 break
799 }
800 }
801
802 src := fd.readbyte[fd.readbyteOffset:]
803 var i int
804 for i = 0; i < len(src) && i < len(b); i++ {
805 x := src[i]
806 if x == 0x1A {
807 if i == 0 {
808 fd.readbyteOffset++
809 }
810 break
811 }
812 b[i] = x
813 }
814 fd.readbyteOffset += i
815 return i, nil
816 }
817
818
819 func (fd *FD) Pread(buf []byte, off int64) (int, error) {
820 if fd.kind == kindPipe {
821
822 return 0, syscall.ESPIPE
823 }
824
825 if err := fd.readWriteLock(); err != nil {
826 return 0, err
827 }
828 defer fd.readWriteUnlock()
829
830 if len(buf) > maxRW {
831 buf = buf[:maxRW]
832 }
833
834 n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
835
836
837
838
839
840 if fd.isBlocking {
841 curoffset, err := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
842 if err != nil {
843 return 0, err
844 }
845 defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart)
846 }
847 o.setOffset(off)
848
849 err = syscall.ReadFile(fd.Sysfd, buf, &qty, &o.o)
850 return qty, err
851 }, pinPtrsFromBuf(buf)...)
852 if err == syscall.ERROR_HANDLE_EOF {
853 err = io.EOF
854 }
855 if len(buf) != 0 {
856 err = fd.eofError(n, err)
857 }
858 return n, err
859 }
860
861
862 func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) {
863 if len(buf) == 0 {
864 return 0, nil, nil
865 }
866 if len(buf) > maxRW {
867 buf = buf[:maxRW]
868 }
869 if err := fd.readLock(); err != nil {
870 return 0, nil, err
871 }
872 defer fd.readUnlock()
873
874 rsa := newWSARsa()
875 defer wsaRsaPool.Put(rsa)
876 n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
877 var flags uint32
878 err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, &rsa.name, &rsa.namelen, &o.o, nil)
879 return qty, err
880 }, unsafe.SliceData(buf), rsa)
881 err = fd.eofError(n, err)
882 if err != nil {
883 return n, nil, err
884 }
885 sa, _ := rsa.name.Sockaddr()
886 return n, sa, nil
887 }
888
889
890 func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) {
891 if len(buf) == 0 {
892 return 0, nil
893 }
894 if len(buf) > maxRW {
895 buf = buf[:maxRW]
896 }
897 if err := fd.readLock(); err != nil {
898 return 0, err
899 }
900 defer fd.readUnlock()
901
902 rsa := newWSARsa()
903 defer wsaRsaPool.Put(rsa)
904 n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
905 var flags uint32
906 err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, &rsa.name, &rsa.namelen, &o.o, nil)
907 return qty, err
908 }, unsafe.SliceData(buf), rsa)
909 err = fd.eofError(n, err)
910 if err != nil {
911 return n, err
912 }
913 rawToSockaddrInet4(&rsa.name, sa4)
914 return n, err
915 }
916
917
918 func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) {
919 if len(buf) == 0 {
920 return 0, nil
921 }
922 if len(buf) > maxRW {
923 buf = buf[:maxRW]
924 }
925 if err := fd.readLock(); err != nil {
926 return 0, err
927 }
928 defer fd.readUnlock()
929
930 rsa := newWSARsa()
931 defer wsaRsaPool.Put(rsa)
932 n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
933 var flags uint32
934 err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, &rsa.name, &rsa.namelen, &o.o, nil)
935 return qty, err
936 }, unsafe.SliceData(buf), rsa)
937 err = fd.eofError(n, err)
938 if err != nil {
939 return n, err
940 }
941 rawToSockaddrInet6(&rsa.name, sa6)
942 return n, err
943 }
944
945
946 func (fd *FD) Write(buf []byte) (int, error) {
947 if fd.kind == kindFile {
948 if err := fd.readWriteLock(); err != nil {
949 return 0, err
950 }
951 defer fd.readWriteUnlock()
952 } else {
953 if err := fd.writeLock(); err != nil {
954 return 0, err
955 }
956 defer fd.writeUnlock()
957 }
958
959 var ntotal int
960 for {
961 max := len(buf)
962 if max-ntotal > maxRW {
963 max = ntotal + maxRW
964 }
965 b := buf[ntotal:max]
966 var n int
967 var err error
968 switch fd.kind {
969 case kindConsole:
970 n, err = fd.writeConsole(b)
971 case kindFile:
972 n, err = fd.execIO('w', func(o *operation) (qty uint32, err error) {
973 o.setOffset(fd.offset)
974 err = syscall.WriteFile(fd.Sysfd, b, &qty, fd.overlapped(o))
975 return qty, err
976 }, pinPtrsFromBuf(b)...)
977 fd.addOffset(n)
978 case kindPipe:
979 n, err = fd.execIO('w', func(o *operation) (qty uint32, err error) {
980 if fd.isBlocking {
981 return fd.execSyncIO(syscall.WriteFile, b)
982 }
983 err = syscall.WriteFile(fd.Sysfd, b, &qty, fd.overlapped(o))
984 return qty, err
985 }, pinPtrsFromBuf(b)...)
986 case kindNet:
987 if race.Enabled {
988 race.ReleaseMerge(unsafe.Pointer(&ioSync))
989 }
990 n, err = fd.execIO('w', func(o *operation) (qty uint32, err error) {
991 err = syscall.WSASend(fd.Sysfd, newWsaBuf(b), 1, &qty, 0, &o.o, nil)
992 return qty, err
993 }, pinPtrsFromBuf(b)...)
994 }
995 ntotal += n
996 if ntotal == len(buf) || err != nil {
997 return ntotal, err
998 }
999 if n == 0 {
1000 return ntotal, io.ErrUnexpectedEOF
1001 }
1002 }
1003 }
1004
1005
1006
1007 func (fd *FD) writeConsole(b []byte) (int, error) {
1008 n := len(b)
1009 runes := make([]rune, 0, 256)
1010 if len(fd.lastbits) > 0 {
1011 b = append(fd.lastbits, b...)
1012 fd.lastbits = nil
1013
1014 }
1015 for len(b) >= utf8.UTFMax || utf8.FullRune(b) {
1016 r, l := utf8.DecodeRune(b)
1017 runes = append(runes, r)
1018 b = b[l:]
1019 }
1020 if len(b) > 0 {
1021 fd.lastbits = make([]byte, len(b))
1022 copy(fd.lastbits, b)
1023 }
1024
1025
1026
1027 const maxWrite = 16000
1028 for len(runes) > 0 {
1029 m := len(runes)
1030 if m > maxWrite {
1031 m = maxWrite
1032 }
1033 chunk := runes[:m]
1034 runes = runes[m:]
1035 uint16s := utf16.Encode(chunk)
1036 for len(uint16s) > 0 {
1037 var written uint32
1038 err := syscall.WriteConsole(fd.Sysfd, &uint16s[0], uint32(len(uint16s)), &written, nil)
1039 if err != nil {
1040 return 0, err
1041 }
1042 uint16s = uint16s[written:]
1043 }
1044 }
1045 return n, nil
1046 }
1047
1048
1049 func (fd *FD) Pwrite(buf []byte, off int64) (int, error) {
1050 if fd.kind == kindPipe {
1051
1052 return 0, syscall.ESPIPE
1053 }
1054
1055 if err := fd.readWriteLock(); err != nil {
1056 return 0, err
1057 }
1058 defer fd.readWriteUnlock()
1059
1060 var ntotal int
1061 for {
1062 max := len(buf)
1063 if max-ntotal > maxRW {
1064 max = ntotal + maxRW
1065 }
1066 b := buf[ntotal:max]
1067 n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
1068
1069
1070
1071
1072
1073 if fd.isBlocking {
1074 curoffset, err := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
1075 if err != nil {
1076 return 0, err
1077 }
1078 defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart)
1079 }
1080 o.setOffset(off + int64(ntotal))
1081
1082 err = syscall.WriteFile(fd.Sysfd, b, &qty, &o.o)
1083 return qty, err
1084 }, pinPtrsFromBuf(b)...)
1085 if n > 0 {
1086 ntotal += n
1087 }
1088 if ntotal == len(buf) || err != nil {
1089 return ntotal, err
1090 }
1091 if n == 0 {
1092 return ntotal, io.ErrUnexpectedEOF
1093 }
1094 }
1095 }
1096
1097
1098 func (fd *FD) Writev(buf *[][]byte) (int64, error) {
1099 if len(*buf) == 0 {
1100 return 0, nil
1101 }
1102 if err := fd.writeLock(); err != nil {
1103 return 0, err
1104 }
1105 defer fd.writeUnlock()
1106 if race.Enabled {
1107 race.ReleaseMerge(unsafe.Pointer(&ioSync))
1108 }
1109 bufs := newWSABufs(buf)
1110 defer freeWSABufs(bufs)
1111 n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
1112 err = syscall.WSASend(fd.Sysfd, &(*bufs)[0], uint32(len(*bufs)), &qty, 0, &o.o, nil)
1113 return qty, err
1114 })
1115 TestHookDidWritev(n)
1116 consume(buf, int64(n))
1117 return int64(n), err
1118 }
1119
1120
1121 func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) {
1122 if err := fd.writeLock(); err != nil {
1123 return 0, err
1124 }
1125 defer fd.writeUnlock()
1126
1127 if len(buf) == 0 {
1128
1129 n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
1130 err = syscall.WSASendto(fd.Sysfd, &syscall.WSABuf{}, 1, &qty, 0, sa, &o.o, nil)
1131 return qty, err
1132 })
1133 return n, err
1134 }
1135
1136 ntotal := 0
1137 for len(buf) > 0 {
1138 b := buf
1139 if len(b) > maxRW {
1140 b = b[:maxRW]
1141 }
1142 n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
1143 err = syscall.WSASendto(fd.Sysfd, newWsaBuf(b), 1, &qty, 0, sa, &o.o, nil)
1144 return qty, err
1145 }, unsafe.SliceData(b))
1146 ntotal += int(n)
1147 if err != nil {
1148 return ntotal, err
1149 }
1150 buf = buf[n:]
1151 }
1152 return ntotal, nil
1153 }
1154
1155
1156 func (fd *FD) WriteToInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) {
1157 if err := fd.writeLock(); err != nil {
1158 return 0, err
1159 }
1160 defer fd.writeUnlock()
1161
1162 if len(buf) == 0 {
1163
1164 n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
1165 err = windows.WSASendtoInet4(fd.Sysfd, &syscall.WSABuf{}, 1, &qty, 0, sa4, &o.o, nil)
1166 return qty, err
1167 })
1168 return n, err
1169 }
1170
1171 ntotal := 0
1172 for len(buf) > 0 {
1173 b := buf
1174 if len(b) > maxRW {
1175 b = b[:maxRW]
1176 }
1177 n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
1178 err = windows.WSASendtoInet4(fd.Sysfd, newWsaBuf(b), 1, &qty, 0, sa4, &o.o, nil)
1179 return qty, err
1180 }, unsafe.SliceData(b))
1181 ntotal += int(n)
1182 if err != nil {
1183 return ntotal, err
1184 }
1185 buf = buf[n:]
1186 }
1187 return ntotal, nil
1188 }
1189
1190
1191 func (fd *FD) WriteToInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) {
1192 if err := fd.writeLock(); err != nil {
1193 return 0, err
1194 }
1195 defer fd.writeUnlock()
1196
1197 if len(buf) == 0 {
1198
1199 n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
1200 err = windows.WSASendtoInet6(fd.Sysfd, &syscall.WSABuf{}, 1, &qty, 0, sa6, &o.o, nil)
1201 return qty, err
1202 })
1203 return n, err
1204 }
1205
1206 ntotal := 0
1207 for len(buf) > 0 {
1208 b := buf
1209 if len(b) > maxRW {
1210 b = b[:maxRW]
1211 }
1212 n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
1213 err = windows.WSASendtoInet6(fd.Sysfd, newWsaBuf(b), 1, &qty, 0, sa6, &o.o, nil)
1214 return qty, err
1215 }, unsafe.SliceData(b))
1216 ntotal += int(n)
1217 if err != nil {
1218 return ntotal, err
1219 }
1220 buf = buf[n:]
1221 }
1222 return ntotal, nil
1223 }
1224
1225
1226
1227
1228 func (fd *FD) ConnectEx(ra syscall.Sockaddr) error {
1229 _, err := fd.execIO('w', func(o *operation) (uint32, error) {
1230 return 0, ConnectExFunc(fd.Sysfd, ra, nil, 0, nil, &o.o)
1231 })
1232 return err
1233 }
1234
1235 func (fd *FD) acceptOne(s syscall.Handle, rawsa []syscall.RawSockaddrAny) (string, error) {
1236
1237 rsan := uint32(unsafe.Sizeof(rawsa[0]))
1238 _, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
1239 err = AcceptFunc(fd.Sysfd, s, (*byte)(unsafe.Pointer(&rawsa[0])), 0, rsan, rsan, &qty, &o.o)
1240 return qty, err
1241
1242 })
1243 if err != nil {
1244 CloseFunc(s)
1245 return "acceptex", err
1246 }
1247
1248
1249 err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.Sysfd)), int32(unsafe.Sizeof(fd.Sysfd)))
1250 if err != nil {
1251 CloseFunc(s)
1252 return "setsockopt", err
1253 }
1254
1255 return "", nil
1256 }
1257
1258
1259
1260 func (fd *FD) Accept(sysSocket func() (syscall.Handle, error)) (syscall.Handle, []syscall.RawSockaddrAny, uint32, string, error) {
1261 if err := fd.readLock(); err != nil {
1262 return syscall.InvalidHandle, nil, 0, "", err
1263 }
1264 defer fd.readUnlock()
1265
1266 var rawsa [2]syscall.RawSockaddrAny
1267 for {
1268 s, err := sysSocket()
1269 if err != nil {
1270 return syscall.InvalidHandle, nil, 0, "", err
1271 }
1272
1273 errcall, err := fd.acceptOne(s, rawsa[:])
1274 if err == nil {
1275 return s, rawsa[:], uint32(unsafe.Sizeof(rawsa[0])), "", nil
1276 }
1277
1278
1279
1280
1281
1282
1283 errno, ok := err.(syscall.Errno)
1284 if !ok {
1285 return syscall.InvalidHandle, nil, 0, errcall, err
1286 }
1287 switch errno {
1288 case syscall.ERROR_NETNAME_DELETED, syscall.WSAECONNRESET:
1289
1290 default:
1291 return syscall.InvalidHandle, nil, 0, errcall, err
1292 }
1293 }
1294 }
1295
1296
1297 func (fd *FD) Seek(offset int64, whence int) (int64, error) {
1298 if fd.kind == kindPipe {
1299 return 0, syscall.ESPIPE
1300 }
1301 if err := fd.readWriteLock(); err != nil {
1302 return 0, err
1303 }
1304 defer fd.readWriteUnlock()
1305
1306 if err := fd.ensureInit(); err != nil {
1307 return 0, err
1308 }
1309 if !fd.isBlocking {
1310
1311
1312 var newOffset int64
1313 switch whence {
1314 case io.SeekStart:
1315 newOffset = offset
1316 case io.SeekCurrent:
1317 newOffset = fd.offset + offset
1318 case io.SeekEnd:
1319 var size int64
1320 if err := windows.GetFileSizeEx(fd.Sysfd, &size); err != nil {
1321 return 0, err
1322 }
1323 newOffset = size + offset
1324 default:
1325 return 0, windows.ERROR_INVALID_PARAMETER
1326 }
1327 if newOffset < 0 {
1328 return 0, windows.ERROR_NEGATIVE_SEEK
1329 }
1330 fd.setOffset(newOffset)
1331 return newOffset, nil
1332 }
1333 n, err := syscall.Seek(fd.Sysfd, offset, whence)
1334 fd.setOffset(n)
1335 return n, err
1336 }
1337
1338
1339 func (fd *FD) Fchmod(mode uint32) error {
1340 if err := fd.incref(); err != nil {
1341 return err
1342 }
1343 defer fd.decref()
1344
1345 var d syscall.ByHandleFileInformation
1346 if err := syscall.GetFileInformationByHandle(fd.Sysfd, &d); err != nil {
1347 return err
1348 }
1349 attrs := d.FileAttributes
1350 if mode&syscall.S_IWRITE != 0 {
1351 attrs &^= syscall.FILE_ATTRIBUTE_READONLY
1352 } else {
1353 attrs |= syscall.FILE_ATTRIBUTE_READONLY
1354 }
1355 if attrs == d.FileAttributes {
1356 return nil
1357 }
1358
1359 var du windows.FILE_BASIC_INFO
1360 du.FileAttributes = attrs
1361 return windows.SetFileInformationByHandle(fd.Sysfd, windows.FileBasicInfo, unsafe.Pointer(&du), uint32(unsafe.Sizeof(du)))
1362 }
1363
1364
1365 func (fd *FD) Fchdir() error {
1366 if err := fd.incref(); err != nil {
1367 return err
1368 }
1369 defer fd.decref()
1370 return syscall.Fchdir(fd.Sysfd)
1371 }
1372
1373
1374 func (fd *FD) GetFileType() (uint32, error) {
1375 if err := fd.incref(); err != nil {
1376 return 0, err
1377 }
1378 defer fd.decref()
1379 return syscall.GetFileType(fd.Sysfd)
1380 }
1381
1382
1383 func (fd *FD) GetFileInformationByHandle(data *syscall.ByHandleFileInformation) error {
1384 if err := fd.incref(); err != nil {
1385 return err
1386 }
1387 defer fd.decref()
1388 return syscall.GetFileInformationByHandle(fd.Sysfd, data)
1389 }
1390
1391
1392 func (fd *FD) RawRead(f func(uintptr) bool) error {
1393 if err := fd.readLock(); err != nil {
1394 return err
1395 }
1396 defer fd.readUnlock()
1397 for {
1398 if f(uintptr(fd.Sysfd)) {
1399 return nil
1400 }
1401
1402
1403
1404 _, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
1405 var flags uint32
1406 if !fd.IsStream {
1407 flags |= windows.MSG_PEEK
1408 }
1409 err = syscall.WSARecv(fd.Sysfd, &syscall.WSABuf{}, 1, &qty, &flags, &o.o, nil)
1410 return qty, err
1411 })
1412 if err == windows.WSAEMSGSIZE {
1413
1414 } else if err != nil {
1415 return err
1416 }
1417 }
1418 }
1419
1420
1421 func (fd *FD) RawWrite(f func(uintptr) bool) error {
1422 if err := fd.writeLock(); err != nil {
1423 return err
1424 }
1425 defer fd.writeUnlock()
1426
1427 if f(uintptr(fd.Sysfd)) {
1428 return nil
1429 }
1430
1431
1432 return syscall.EWINDOWS
1433 }
1434
1435 func sockaddrInet4ToRaw(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet4) int32 {
1436 *rsa = syscall.RawSockaddrAny{}
1437 raw := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa))
1438 raw.Family = syscall.AF_INET
1439 p := (*[2]byte)(unsafe.Pointer(&raw.Port))
1440 p[0] = byte(sa.Port >> 8)
1441 p[1] = byte(sa.Port)
1442 raw.Addr = sa.Addr
1443 return int32(unsafe.Sizeof(*raw))
1444 }
1445
1446 func sockaddrInet6ToRaw(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet6) int32 {
1447 *rsa = syscall.RawSockaddrAny{}
1448 raw := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa))
1449 raw.Family = syscall.AF_INET6
1450 p := (*[2]byte)(unsafe.Pointer(&raw.Port))
1451 p[0] = byte(sa.Port >> 8)
1452 p[1] = byte(sa.Port)
1453 raw.Scope_id = sa.ZoneId
1454 raw.Addr = sa.Addr
1455 return int32(unsafe.Sizeof(*raw))
1456 }
1457
1458 func rawToSockaddrInet4(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet4) {
1459 pp := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa))
1460 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
1461 sa.Port = int(p[0])<<8 + int(p[1])
1462 sa.Addr = pp.Addr
1463 }
1464
1465 func rawToSockaddrInet6(rsa *syscall.RawSockaddrAny, sa *syscall.SockaddrInet6) {
1466 pp := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa))
1467 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
1468 sa.Port = int(p[0])<<8 + int(p[1])
1469 sa.ZoneId = pp.Scope_id
1470 sa.Addr = pp.Addr
1471 }
1472
1473 func sockaddrToRaw(rsa *syscall.RawSockaddrAny, sa syscall.Sockaddr) (int32, error) {
1474 switch sa := sa.(type) {
1475 case *syscall.SockaddrInet4:
1476 sz := sockaddrInet4ToRaw(rsa, sa)
1477 return sz, nil
1478 case *syscall.SockaddrInet6:
1479 sz := sockaddrInet6ToRaw(rsa, sa)
1480 return sz, nil
1481 default:
1482 return 0, syscall.EWINDOWS
1483 }
1484 }
1485
1486
1487 func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.Sockaddr, error) {
1488 if err := fd.readLock(); err != nil {
1489 return 0, 0, 0, nil, err
1490 }
1491 defer fd.readUnlock()
1492
1493 if len(p) > maxRW {
1494 p = p[:maxRW]
1495 }
1496
1497 rsa := newWSARsa()
1498 defer wsaRsaPool.Put(rsa)
1499 msg := newWSAMsg(p, oob, flags, rsa)
1500 defer freeWSAMsg(msg)
1501 n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
1502 err = windows.WSARecvMsg(fd.Sysfd, msg, &qty, &o.o, nil)
1503 return qty, err
1504 }, rsa, msg)
1505 err = fd.eofError(n, err)
1506 var sa syscall.Sockaddr
1507 if err == nil {
1508 sa, err = msg.Name.Sockaddr()
1509 }
1510 return n, int(msg.Control.Len), int(msg.Flags), sa, err
1511 }
1512
1513
1514 func (fd *FD) ReadMsgInet4(p []byte, oob []byte, flags int, sa4 *syscall.SockaddrInet4) (int, int, int, error) {
1515 if err := fd.readLock(); err != nil {
1516 return 0, 0, 0, err
1517 }
1518 defer fd.readUnlock()
1519
1520 if len(p) > maxRW {
1521 p = p[:maxRW]
1522 }
1523
1524 rsa := newWSARsa()
1525 defer wsaRsaPool.Put(rsa)
1526 msg := newWSAMsg(p, oob, flags, rsa)
1527 defer freeWSAMsg(msg)
1528 n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
1529 err = windows.WSARecvMsg(fd.Sysfd, msg, &qty, &o.o, nil)
1530 return qty, err
1531 }, rsa, msg)
1532 err = fd.eofError(n, err)
1533 if err == nil {
1534 rawToSockaddrInet4(msg.Name, sa4)
1535 }
1536 return n, int(msg.Control.Len), int(msg.Flags), err
1537 }
1538
1539
1540 func (fd *FD) ReadMsgInet6(p []byte, oob []byte, flags int, sa6 *syscall.SockaddrInet6) (int, int, int, error) {
1541 if err := fd.readLock(); err != nil {
1542 return 0, 0, 0, err
1543 }
1544 defer fd.readUnlock()
1545
1546 if len(p) > maxRW {
1547 p = p[:maxRW]
1548 }
1549
1550 rsa := newWSARsa()
1551 defer wsaRsaPool.Put(rsa)
1552 msg := newWSAMsg(p, oob, flags, rsa)
1553 defer freeWSAMsg(msg)
1554 n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
1555 err = windows.WSARecvMsg(fd.Sysfd, msg, &qty, &o.o, nil)
1556 return qty, err
1557 }, rsa, msg)
1558 err = fd.eofError(n, err)
1559 if err == nil {
1560 rawToSockaddrInet6(msg.Name, sa6)
1561 }
1562 return n, int(msg.Control.Len), int(msg.Flags), err
1563 }
1564
1565
1566 func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, error) {
1567 if len(p) > maxRW {
1568 return 0, 0, errors.New("packet is too large (only 1GB is allowed)")
1569 }
1570
1571 if err := fd.writeLock(); err != nil {
1572 return 0, 0, err
1573 }
1574 defer fd.writeUnlock()
1575
1576 var rsa *wsaRsa
1577 if sa != nil {
1578 rsa = newWSARsa()
1579 defer wsaRsaPool.Put(rsa)
1580 var err error
1581 rsa.namelen, err = sockaddrToRaw(&rsa.name, sa)
1582 if err != nil {
1583 return 0, 0, err
1584 }
1585 }
1586 msg := newWSAMsg(p, oob, 0, rsa)
1587 defer freeWSAMsg(msg)
1588 n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
1589 err = windows.WSASendMsg(fd.Sysfd, msg, 0, nil, &o.o, nil)
1590 return qty, err
1591 }, rsa, msg)
1592 return n, int(msg.Control.Len), err
1593 }
1594
1595
1596 func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (int, int, error) {
1597 if len(p) > maxRW {
1598 return 0, 0, errors.New("packet is too large (only 1GB is allowed)")
1599 }
1600
1601 if err := fd.writeLock(); err != nil {
1602 return 0, 0, err
1603 }
1604 defer fd.writeUnlock()
1605
1606 var rsa *wsaRsa
1607 if sa != nil {
1608 rsa = newWSARsa()
1609 defer wsaRsaPool.Put(rsa)
1610 rsa.namelen = sockaddrInet4ToRaw(&rsa.name, sa)
1611 }
1612 msg := newWSAMsg(p, oob, 0, rsa)
1613 defer freeWSAMsg(msg)
1614 n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
1615 err = windows.WSASendMsg(fd.Sysfd, msg, 0, nil, &o.o, nil)
1616 return qty, err
1617 }, rsa, msg)
1618 return n, int(msg.Control.Len), err
1619 }
1620
1621
1622 func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (int, int, error) {
1623 if len(p) > maxRW {
1624 return 0, 0, errors.New("packet is too large (only 1GB is allowed)")
1625 }
1626
1627 if err := fd.writeLock(); err != nil {
1628 return 0, 0, err
1629 }
1630 defer fd.writeUnlock()
1631
1632 var rsa *wsaRsa
1633 if sa != nil {
1634 rsa = newWSARsa()
1635 defer wsaRsaPool.Put(rsa)
1636 rsa.namelen = sockaddrInet6ToRaw(&rsa.name, sa)
1637 }
1638 msg := newWSAMsg(p, oob, 0, rsa)
1639 defer freeWSAMsg(msg)
1640 n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
1641 err = windows.WSASendMsg(fd.Sysfd, msg, 0, nil, &o.o, nil)
1642 return qty, err
1643 }, rsa, msg)
1644 return n, int(msg.Control.Len), err
1645 }
1646
1647 func DupCloseOnExec(fd int) (int, string, error) {
1648 proc, err := syscall.GetCurrentProcess()
1649 if err != nil {
1650 return 0, "GetCurrentProcess", err
1651 }
1652
1653 var nfd syscall.Handle
1654 const inherit = false
1655 if err := syscall.DuplicateHandle(proc, syscall.Handle(fd), proc, &nfd, 0, inherit, syscall.DUPLICATE_SAME_ACCESS); err != nil {
1656 return 0, "DuplicateHandle", err
1657 }
1658 return int(nfd), "", nil
1659 }
1660
View as plain text