github.com/JimmyHuang454/JLS-go@v0.0.0-20230831150107-90d536585ba0/internal/poll/sendfile_windows.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package poll 6 7 import ( 8 "io" 9 "syscall" 10 ) 11 12 // SendFile wraps the TransmitFile call. 13 func SendFile(fd *FD, src syscall.Handle, n int64) (written int64, err error) { 14 if fd.kind == kindPipe { 15 // TransmitFile does not work with pipes 16 return 0, syscall.ESPIPE 17 } 18 19 if err := fd.writeLock(); err != nil { 20 return 0, err 21 } 22 defer fd.writeUnlock() 23 24 o := &fd.wop 25 o.handle = src 26 27 // TODO(brainman): skip calling syscall.Seek if OS allows it 28 curpos, err := syscall.Seek(o.handle, 0, io.SeekCurrent) 29 if err != nil { 30 return 0, err 31 } 32 33 if n <= 0 { // We don't know the size of the file so infer it. 34 // Find the number of bytes offset from curpos until the end of the file. 35 n, err = syscall.Seek(o.handle, -curpos, io.SeekEnd) 36 if err != nil { 37 return 38 } 39 // Now seek back to the original position. 40 if _, err = syscall.Seek(o.handle, curpos, io.SeekStart); err != nil { 41 return 42 } 43 } 44 45 // TransmitFile can be invoked in one call with at most 46 // 2,147,483,646 bytes: the maximum value for a 32-bit integer minus 1. 47 // See https://docs.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-transmitfile 48 const maxChunkSizePerCall = int64(0x7fffffff - 1) 49 50 for n > 0 { 51 chunkSize := maxChunkSizePerCall 52 if chunkSize > n { 53 chunkSize = n 54 } 55 56 o.qty = uint32(chunkSize) 57 o.o.Offset = uint32(curpos) 58 o.o.OffsetHigh = uint32(curpos >> 32) 59 60 nw, err := execIO(o, func(o *operation) error { 61 return syscall.TransmitFile(o.fd.Sysfd, o.handle, o.qty, 0, &o.o, nil, syscall.TF_WRITE_BEHIND) 62 }) 63 if err != nil { 64 return written, err 65 } 66 67 curpos += int64(nw) 68 69 // Some versions of Windows (Windows 10 1803) do not set 70 // file position after TransmitFile completes. 71 // So just use Seek to set file position. 72 if _, err = syscall.Seek(o.handle, curpos, io.SeekStart); err != nil { 73 return written, err 74 } 75 76 n -= int64(nw) 77 written += int64(nw) 78 } 79 80 return 81 }