1 // Copyright 2011 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 "io" 9 "os" 10 "syscall" 11 ) 12 13 // sendFile copies the contents of r to c using the TransmitFile 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 // 21 // Note that sendfile for windows does not suppport >2GB file. 22 func sendFile(fd *netFD, r io.Reader) (written int64, err error, handled bool) { 23 var n int64 = 0 // by default, copy until EOF 24 25 lr, ok := r.(*io.LimitedReader) 26 if ok { 27 n, r = lr.N, lr.R 28 if n <= 0 { 29 return 0, nil, true 30 } 31 } 32 f, ok := r.(*os.File) 33 if !ok { 34 return 0, nil, false 35 } 36 37 if err := fd.writeLock(); err != nil { 38 return 0, err, true 39 } 40 defer fd.writeUnlock() 41 42 o := &fd.wop 43 o.qty = uint32(n) 44 o.handle = syscall.Handle(f.Fd()) 45 done, err := wsrv.ExecIO(o, "TransmitFile", func(o *operation) error { 46 return syscall.TransmitFile(o.fd.sysfd, o.handle, o.qty, 0, &o.o, nil, syscall.TF_WRITE_BEHIND) 47 }) 48 if err != nil { 49 return 0, os.NewSyscallError("transmitfile", err), false 50 } 51 if lr != nil { 52 lr.N -= int64(done) 53 } 54 return int64(done), nil, true 55 } 56