blob: f3f3b54b886b034b6a7d218d377d0177270bc51d [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 Vyukov23e15f72013-08-09 21:43:00 +040037 if err := fd.writeLock(); err != nil {
Russ Cox5e4e3d82012-02-14 00:40:37 -050038 return 0, err, true
39 }
Dmitriy Vyukov23e15f72013-08-09 21:43:00 +040040 defer fd.writeUnlock()
41
Dmitriy Vyukov04b1cfa2013-08-06 14:40:10 +040042 o := &fd.wop
Dmitriy Vyukov04b1cfa2013-08-06 14:40:10 +040043 o.qty = uint32(n)
44 o.handle = syscall.Handle(f.Fd())
Alex Brainman11320fa2013-08-27 14:53:57 +100045 done, err := wsrv.ExecIO(o, "TransmitFile", func(o *operation) error {
Dmitriy Vyukov04b1cfa2013-08-06 14:40:10 +040046 return syscall.TransmitFile(o.fd.sysfd, o.handle, o.qty, 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
47 })
Yasuhiro Matsumoto13740972011-06-11 13:24:48 +100048 if err != nil {
Mikio Hara055ecb72015-04-21 21:20:15 +090049 return 0, os.NewSyscallError("transmitfile", err), false
Yasuhiro Matsumoto13740972011-06-11 13:24:48 +100050 }
51 if lr != nil {
52 lr.N -= int64(done)
53 }
54 return int64(done), nil, true
55}