libgo: update to go1.9
[official-gcc.git] / libgo / go / net / sendfile_solaris.go
blob63ca9d47b8ae288219b34aaa8e844049e74c037e
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.
5 package net
7 import (
8 "internal/poll"
9 "io"
10 "os"
13 // sendFile copies the contents of r to c using the sendfile
14 // system call to minimize copies.
16 // if handled == true, sendFile returns the number of bytes copied and any
17 // non-EOF error.
19 // if handled == false, sendFile performed no work.
20 func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
21 // Solaris uses 0 as the "until EOF" value. If you pass in more bytes than the
22 // file contains, it will loop back to the beginning ad nauseam until it's sent
23 // exactly the number of bytes told to. As such, we need to know exactly how many
24 // bytes to send.
25 var remain int64 = 0
27 lr, ok := r.(*io.LimitedReader)
28 if ok {
29 remain, r = lr.N, lr.R
30 if remain <= 0 {
31 return 0, nil, true
34 f, ok := r.(*os.File)
35 if !ok {
36 return 0, nil, false
39 if remain == 0 {
40 fi, err := f.Stat()
41 if err != nil {
42 return 0, err, false
45 remain = fi.Size()
48 // The other quirk with Solaris's sendfile implementation is that it doesn't
49 // use the current position of the file -- if you pass it offset 0, it starts
50 // from offset 0. There's no way to tell it "start from current position", so
51 // we have to manage that explicitly.
52 pos, err := f.Seek(0, io.SeekCurrent)
53 if err != nil {
54 return 0, err, false
57 written, err = poll.SendFile(&c.pfd, int(f.Fd()), pos, remain)
59 if lr != nil {
60 lr.N = remain - written
62 return written, wrapSyscallError("sendfile", err), written > 0