Source file
src/internal/poll/sendfile_windows.go
1
2
3
4
5 package poll
6
7 import (
8 "io"
9 "syscall"
10 )
11
12
13 func SendFile(fd *FD, src syscall.Handle, n int64) (written int64, err error) {
14 defer func() {
15 TestHookDidSendFile(fd, 0, written, err, written > 0)
16 }()
17 if fd.kind == kindPipe {
18
19 return 0, syscall.ESPIPE
20 }
21 if ft, _ := syscall.GetFileType(src); ft == syscall.FILE_TYPE_PIPE {
22 return 0, syscall.ESPIPE
23 }
24
25 if err := fd.writeLock(); err != nil {
26 return 0, err
27 }
28 defer fd.writeUnlock()
29
30 o := &fd.wop
31 o.handle = src
32
33
34 curpos, err := syscall.Seek(o.handle, 0, io.SeekCurrent)
35 if err != nil {
36 return 0, err
37 }
38
39 if n <= 0 {
40
41 n, err = syscall.Seek(o.handle, -curpos, io.SeekEnd)
42 if err != nil {
43 return
44 }
45
46 if _, err = syscall.Seek(o.handle, curpos, io.SeekStart); err != nil {
47 return
48 }
49 }
50
51
52
53
54 const maxChunkSizePerCall = int64(0x7fffffff - 1)
55
56 for n > 0 {
57 chunkSize := maxChunkSizePerCall
58 if chunkSize > n {
59 chunkSize = n
60 }
61
62 o.qty = uint32(chunkSize)
63 o.o.Offset = uint32(curpos)
64 o.o.OffsetHigh = uint32(curpos >> 32)
65
66 nw, err := execIO(o, func(o *operation) error {
67 return syscall.TransmitFile(o.fd.Sysfd, o.handle, o.qty, 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
68 })
69 if err != nil {
70 return written, err
71 }
72
73 curpos += int64(nw)
74
75
76
77
78 if _, err = syscall.Seek(o.handle, curpos, io.SeekStart); err != nil {
79 return written, err
80 }
81
82 n -= int64(nw)
83 written += int64(nw)
84 }
85
86 return
87 }
88
View as plain text