diff options
author | Tobias Klauser <tklauser@distanz.ch> | 2018-04-05 12:20:12 +0200 |
---|---|---|
committer | Tobias Klauser <tobias.klauser@gmail.com> | 2018-04-06 14:48:05 +0000 |
commit | 84b784a84f89f94ceae952743aa447a6a9c95f32 (patch) | |
tree | 1443b996d7845ff26a2e9d3d2e673506671160d8 /src/net/sendfile_unix_alt.go | |
parent | 92c29ef94116f64263444a07748192b3857be9f1 (diff) | |
download | go-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.go | 67 |
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 +} |