aboutsummaryrefslogtreecommitdiff
path: root/src/net
diff options
context:
space:
mode:
Diffstat (limited to 'src/net')
-rw-r--r--src/net/sendfile_test.go14
-rw-r--r--src/net/sendfile_unix_alt.go41
2 files changed, 15 insertions, 40 deletions
diff --git a/src/net/sendfile_test.go b/src/net/sendfile_test.go
index 4f3411565b..64b33a54e2 100644
--- a/src/net/sendfile_test.go
+++ b/src/net/sendfile_test.go
@@ -69,7 +69,10 @@ func expectSendfile(t *testing.T, wantConn Conn, f func()) {
}
}
-func TestSendfile(t *testing.T) {
+func TestSendfile(t *testing.T) { testSendfile(t, 0) }
+func TestSendfileWithExactLimit(t *testing.T) { testSendfile(t, newtonLen) }
+func TestSendfileWithLimitLargerThanFile(t *testing.T) { testSendfile(t, newtonLen*2) }
+func testSendfile(t *testing.T, limit int64) {
ln := newLocalListener(t, "tcp")
defer ln.Close()
@@ -104,7 +107,14 @@ func TestSendfile(t *testing.T) {
sbytes, err = io.Copy(conn, f)
default:
expectSendfile(t, conn, func() {
- sbytes, err = io.Copy(conn, f)
+ if limit > 0 {
+ sbytes, err = io.CopyN(conn, f, limit)
+ if err == io.EOF && limit > newtonLen {
+ err = nil
+ }
+ } else {
+ sbytes, err = io.Copy(conn, f)
+ }
})
}
if err != nil {
diff --git a/src/net/sendfile_unix_alt.go b/src/net/sendfile_unix_alt.go
index 9e46c4e607..db788753f1 100644
--- a/src/net/sendfile_unix_alt.go
+++ b/src/net/sendfile_unix_alt.go
@@ -9,7 +9,6 @@ package net
import (
"internal/poll"
"io"
- "io/fs"
"syscall"
)
@@ -23,13 +22,7 @@ const supportsSendfile = true
//
// if handled == false, sendFile performed no work.
func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
- // Darwin, FreeBSD, DragonFly and Solaris use 0 as the "until EOF" value.
- // If you pass in more bytes than the file contains, it will
- // loop back to the beginning ad nauseam until it's sent
- // exactly the number of bytes told to. As such, we need to
- // know exactly how many bytes to send.
- var remain int64 = 0
-
+ var remain int64 = 0 // 0 writes the entire file
lr, ok := r.(*io.LimitedReader)
if ok {
remain, r = lr.N, lr.R
@@ -39,34 +32,11 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
}
// r might be an *os.File or an os.fileWithoutWriteTo.
// Type assert to an interface rather than *os.File directly to handle the latter case.
- f, ok := r.(interface {
- fs.File
- io.Seeker
- syscall.Conn
- })
+ f, ok := r.(syscall.Conn)
if !ok {
return 0, nil, false
}
- if remain == 0 {
- fi, err := f.Stat()
- if err != nil {
- return 0, err, false
- }
-
- remain = fi.Size()
- }
-
- // The other quirk with Darwin/FreeBSD/DragonFly/Solaris's sendfile
- // implementation is that it doesn't use the current position
- // of the file -- if you pass it offset 0, it starts from
- // offset 0. There's no way to tell it "start from current
- // position", so we have to manage that explicitly.
- pos, err := f.Seek(0, io.SeekCurrent)
- if err != nil {
- return 0, err, false
- }
-
sc, err := f.SyscallConn()
if err != nil {
return 0, nil, false
@@ -74,7 +44,7 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
var werr error
err = sc.Read(func(fd uintptr) bool {
- written, werr, handled = poll.SendFile(&c.pfd, int(fd), pos, remain)
+ written, werr, handled = poll.SendFile(&c.pfd, int(fd), remain)
return true
})
if err == nil {
@@ -85,10 +55,5 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
lr.N = remain - written
}
- _, err1 := f.Seek(written, io.SeekCurrent)
- if err1 != nil && err == nil {
- return written, err1, handled
- }
-
return written, wrapSyscallError("sendfile", err), handled
}