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
5package net
6
7import (
8	"internal/poll"
9	"io"
10	"os"
11)
12
13const supportsSendfile = true
14
15// sendFile copies the contents of r to c using the sendfile
16// system call to minimize copies.
17//
18// if handled == true, sendFile returns the number (potentially zero) of bytes
19// copied and any non-EOF error.
20//
21// if handled == false, sendFile performed no work.
22func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
23	var remain int64 = 1<<63 - 1 // by default, copy until EOF
24
25	lr, ok := r.(*io.LimitedReader)
26	if ok {
27		remain, r = lr.N, lr.R
28		if remain <= 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	sc, err := f.SyscallConn()
38	if err != nil {
39		return 0, nil, false
40	}
41
42	var werr error
43	err = sc.Read(func(fd uintptr) bool {
44		written, werr, handled = poll.SendFile(&c.pfd, int(fd), remain)
45		return true
46	})
47	if err == nil {
48		err = werr
49	}
50
51	if lr != nil {
52		lr.N = remain - written
53	}
54	return written, wrapSyscallError("sendfile", err), handled
55}
56