blob: e9b9f91da54aaea646a214528d0835b9bd5e4c8e [file] [log] [blame]
Yasuhiro Matsumoto13740972011-06-11 13:24:48 +10001// 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
5package net
6
7import (
8 "io"
9 "os"
10 "syscall"
11)
12
Yasuhiro Matsumoto13740972011-06-11 13:24:48 +100013// 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.
Dmitriy Vyukov04b1cfa2013-08-06 14:40:10 +040022func sendFile(fd *netFD, r io.Reader) (written int64, err error, handled bool) {
Yasuhiro Matsumoto13740972011-06-11 13:24:48 +100023 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
Dmitriy Vyukov04b1cfa2013-08-06 14:40:10 +040037 if err := fd.incref(false); err != nil {
Russ Cox5e4e3d82012-02-14 00:40:37 -050038 return 0, err, true
39 }
Dmitriy Vyukov04b1cfa2013-08-06 14:40:10 +040040 defer fd.decref()
41 o := &fd.wop
42 o.mu.Lock()
43 defer o.mu.Unlock()
44 o.qty = uint32(n)
45 o.handle = syscall.Handle(f.Fd())
46 done, err := iosrv.ExecIO(o, "TransmitFile", func(o *operation) error {
47 return syscall.TransmitFile(o.fd.sysfd, o.handle, o.qty, 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
48 })
Yasuhiro Matsumoto13740972011-06-11 13:24:48 +100049 if err != nil {
50 return 0, err, false
51 }
52 if lr != nil {
53 lr.N -= int64(done)
54 }
55 return int64(done), nil, true
56}