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 if fi.Mode()&(fs.ModeSymlink|fs.ModeDevice|fs.ModeCharDevice|fs.ModeIrregular) != 0 {
57 return 0, nil, false
58 }
59
60 remain = fi.Size()
61 }
62
63
64
65
66
67
68 pos, err := f.Seek(0, io.SeekCurrent)
69 if err != nil {
70 return 0, err, false
71 }
72
73 sc, err := f.SyscallConn()
74 if err != nil {
75 return 0, nil, false
76 }
77
78 var werr error
79 err = sc.Read(func(fd uintptr) bool {
80 written, werr, handled = poll.SendFile(&c.pfd, int(fd), pos, remain)
81 return true
82 })
83 if err == nil {
84 err = werr
85 }
86
87 if lr != nil {
88 lr.N = remain - written
89 }
90
91 _, err1 := f.Seek(written, io.SeekCurrent)
92 if err1 != nil && err == nil {
93 return written, err1, handled
94 }
95
96 return written, wrapSyscallError("sendfile", err), handled
97 }
98
View as plain text