summaryrefslogtreecommitdiff
path: root/src/net/sendfile_unix_alt.go
diff options
context:
space:
mode:
authorTobias Klauser <tklauser@distanz.ch>2018-04-05 12:20:12 +0200
committerTobias Klauser <tobias.klauser@gmail.com>2018-04-06 14:48:05 +0000
commit84b784a84f89f94ceae952743aa447a6a9c95f32 (patch)
tree1443b996d7845ff26a2e9d3d2e673506671160d8 /src/net/sendfile_unix_alt.go
parent92c29ef94116f64263444a07748192b3857be9f1 (diff)
downloadgo-git-84b784a84f89f94ceae952743aa447a6a9c95f32.tar.gz
net: use same sendFile for freebsd/dragonfly and solaris
FreeBSD/Dragonfly and Solaris have identical implementations of sendFile. Keep one and adjust the comments accordingly. Change-Id: I77b0f88a4816dd6e40f5cb33919c44606401ac6b Reviewed-on: https://go-review.googlesource.com/104915 Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/net/sendfile_unix_alt.go')
-rw-r--r--src/net/sendfile_unix_alt.go67
1 files changed, 67 insertions, 0 deletions
diff --git a/src/net/sendfile_unix_alt.go b/src/net/sendfile_unix_alt.go
new file mode 100644
index 0000000000..97aeebbed2
--- /dev/null
+++ b/src/net/sendfile_unix_alt.go
@@ -0,0 +1,67 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build dragonfly freebsd solaris
+
+package net
+
+import (
+ "internal/poll"
+ "io"
+ "os"
+)
+
+// sendFile copies the contents of r to c using the sendfile
+// system call to minimize copies.
+//
+// if handled == true, sendFile returns the number of bytes copied and any
+// non-EOF error.
+//
+// if handled == false, sendFile performed no work.
+func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
+ // 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
+
+ lr, ok := r.(*io.LimitedReader)
+ if ok {
+ remain, r = lr.N, lr.R
+ if remain <= 0 {
+ return 0, nil, true
+ }
+ }
+ f, ok := r.(*os.File)
+ 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 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
+ }
+
+ written, err = poll.SendFile(&c.pfd, int(f.Fd()), pos, remain)
+
+ if lr != nil {
+ lr.N = remain - written
+ }
+ return written, wrapSyscallError("sendfile", err), written > 0
+}