github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/internal/poll/sendfile_solaris.go (about) 1 // Copyright 2015 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 "syscall" 8 9 // Not strictly needed, but very helpful for debugging, see issue #10221. 10 // 11 //go:cgo_import_dynamic _ _ "libsendfile.so" 12 //go:cgo_import_dynamic _ _ "libsocket.so" 13 14 // maxSendfileSize is the largest chunk size we ask the kernel to copy 15 // at a time. 16 const maxSendfileSize int = 4 << 20 17 18 // SendFile wraps the sendfile system call. 19 func SendFile(dstFD *FD, src int, pos, remain int64) (written int64, err error, handled bool) { 20 if err := dstFD.writeLock(); err != nil { 21 return 0, err, false 22 } 23 defer dstFD.writeUnlock() 24 25 if err := dstFD.pd.prepareWrite(dstFD.isFile); err != nil { 26 return 0, err, false 27 } 28 29 dst := dstFD.Sysfd 30 for remain > 0 { 31 n := maxSendfileSize 32 if int64(n) > remain { 33 n = int(remain) 34 } 35 pos1 := pos 36 n, err = syscall.Sendfile(dst, src, &pos1, n) 37 if err == syscall.EAGAIN || err == syscall.EINTR { 38 // partial write may have occurred 39 n = int(pos1 - pos) 40 } 41 if n > 0 { 42 pos += int64(n) 43 written += int64(n) 44 remain -= int64(n) 45 continue 46 } else if err != syscall.EAGAIN && err != syscall.EINTR { 47 // This includes syscall.ENOSYS (no kernel 48 // support) and syscall.EINVAL (fd types which 49 // don't implement sendfile), and other errors. 50 // We should end the loop when there is no error 51 // returned from sendfile(2) or it is not a retryable error. 52 break 53 } 54 if err == syscall.EINTR { 55 continue 56 } 57 if err = dstFD.pd.waitWrite(dstFD.isFile); err != nil { 58 break 59 } 60 } 61 handled = written != 0 || (err != syscall.ENOSYS && err != syscall.EINVAL) 62 return 63 }