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.
13 // Not strictly needed, but very helpful for debugging, see issue #10221.
14 //go:cgo_import_dynamic _ _ "libsendfile.so"
15 //go:cgo_import_dynamic _ _ "libsocket.so"
17 // maxSendfileSize is the largest chunk size we ask the kernel to copy
19 const maxSendfileSize
int = 4 << 20
21 // sendFile copies the contents of r to c using the sendfile
22 // system call to minimize copies.
24 // if handled == true, sendFile returns the number of bytes copied and any
27 // if handled == false, sendFile performed no work.
28 func sendFile(c
*netFD
, r io
.Reader
) (written
int64, err error
, handled
bool) {
29 // Solaris uses 0 as the "until EOF" value. If you pass in more bytes than the
30 // file contains, it will loop back to the beginning ad nauseam until it's sent
31 // exactly the number of bytes told to. As such, we need to know exactly how many
35 lr
, ok
:= r
.(*io
.LimitedReader
)
37 remain
, r
= lr
.N
, lr
.R
56 // The other quirk with Solaris's sendfile implementation is that it doesn't
57 // use the current position of the file -- if you pass it offset 0, it starts
58 // from offset 0. There's no way to tell it "start from current position", so
59 // we have to manage that explicitly.
60 pos
, err
:= f
.Seek(0, io
.SeekCurrent
)
65 if err
:= c
.writeLock(); err
!= nil {
74 if int64(n
) > remain
{
78 n
, err1
:= syscall
.Sendfile(dst
, src
, &pos1
, n
)
79 if err1
== syscall
.EAGAIN || err1
== syscall
.EINTR
{
80 // partial write may have occurred
81 if n
= int(pos1
- pos
); n
== 0 {
82 // nothing more to write
91 if n
== 0 && err1
== nil {
94 if err1
== syscall
.EAGAIN
{
95 if err1
= c
.pd
.waitWrite(); err1
== nil {
99 if err1
== syscall
.EINTR
{
103 // This includes syscall.ENOSYS (no kernel
104 // support) and syscall.EINVAL (fd types which
105 // don't implement sendfile)
114 err
= os
.NewSyscallError("sendfile", err
)
116 return written
, err
, written
> 0