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