Source file
src/internal/poll/sendfile_linux.go
1
2
3
4
5 package poll
6
7 import "syscall"
8
9
10
11 const maxSendfileSize int = 4 << 20
12
13
14 func SendFile(dstFD *FD, src int, remain int64) (written int64, err error, handled bool) {
15 defer func() {
16 TestHookDidSendFile(dstFD, src, written, err, handled)
17 }()
18 if err := dstFD.writeLock(); err != nil {
19 return 0, err, false
20 }
21 defer dstFD.writeUnlock()
22
23 if err := dstFD.pd.prepareWrite(dstFD.isFile); err != nil {
24 return 0, err, false
25 }
26
27 dst := dstFD.Sysfd
28 for remain > 0 {
29 n := maxSendfileSize
30 if int64(n) > remain {
31 n = int(remain)
32 }
33 n, err = syscall.Sendfile(dst, src, nil, n)
34 if n > 0 {
35 written += int64(n)
36 remain -= int64(n)
37 continue
38 } else if err != syscall.EAGAIN && err != syscall.EINTR {
39
40
41
42
43
44 break
45 }
46 if err == syscall.EINTR {
47 continue
48 }
49 if err = dstFD.pd.waitWrite(dstFD.isFile); err != nil {
50 break
51 }
52 }
53 if err == syscall.EAGAIN {
54 err = nil
55 }
56 handled = written != 0 || (err != syscall.ENOSYS && err != syscall.EINVAL)
57 return
58 }
59
View as plain text