Source file
src/net/sendfile_unix_alt.go
1
2
3
4
5
6
7 package net
8
9 import (
10 "internal/poll"
11 "io"
12 "io/fs"
13 "syscall"
14 )
15
16 const supportsSendfile = true
17
18
19
20
21
22
23
24
25 func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
26
27
28
29
30
31 var remain int64 = 0
32
33 lr, ok := r.(*io.LimitedReader)
34 if ok {
35 remain, r = lr.N, lr.R
36 if remain <= 0 {
37 return 0, nil, true
38 }
39 }
40
41
42 f, ok := r.(interface {
43 fs.File
44 io.Seeker
45 syscall.Conn
46 })
47 if !ok {
48 return 0, nil, false
49 }
50
51 if remain == 0 {
52 fi, err := f.Stat()
53 if err != nil {
54 return 0, err, false
55 }
56
57 remain = fi.Size()
58 }
59
60
61
62
63
64
65 pos, err := f.Seek(0, io.SeekCurrent)
66 if err != nil {
67 return 0, err, false
68 }
69
70 sc, err := f.SyscallConn()
71 if err != nil {
72 return 0, nil, false
73 }
74
75 var werr error
76 err = sc.Read(func(fd uintptr) bool {
77 written, werr, handled = poll.SendFile(&c.pfd, int(fd), pos, remain)
78 return true
79 })
80 if err == nil {
81 err = werr
82 }
83
84 if lr != nil {
85 lr.N = remain - written
86 }
87
88 _, err1 := f.Seek(written, io.SeekCurrent)
89 if err1 != nil && err == nil {
90 return written, err1, handled
91 }
92
93 return written, wrapSyscallError("sendfile", err), handled
94 }
95
View as plain text