github.com/slayercat/go@v0.0.0-20170428012452-c51559813f61/src/net/sendfile_solaris.go (about) 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. 4 5 package net 6 7 import ( 8 "internal/poll" 9 "io" 10 "os" 11 ) 12 13 // sendFile copies the contents of r to c using the sendfile 14 // system call to minimize copies. 15 // 16 // if handled == true, sendFile returns the number of bytes copied and any 17 // non-EOF error. 18 // 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 26 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 32 } 33 } 34 f, ok := r.(*os.File) 35 if !ok { 36 return 0, nil, false 37 } 38 39 if remain == 0 { 40 fi, err := f.Stat() 41 if err != nil { 42 return 0, err, false 43 } 44 45 remain = fi.Size() 46 } 47 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 55 } 56 57 written, err = poll.SendFile(&c.pfd, int(f.Fd()), pos, remain) 58 59 if lr != nil { 60 lr.N = remain - written 61 } 62 return written, wrapSyscallError("sendfile", err), written > 0 63 }