sendfile_windows.go 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. // Copyright 2011 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package net
  5. import (
  6. "io"
  7. "os"
  8. "syscall"
  9. )
  10. // sendFile copies the contents of r to c using the TransmitFile
  11. // system call to minimize copies.
  12. //
  13. // if handled == true, sendFile returns the number of bytes copied and any
  14. // non-EOF error.
  15. //
  16. // if handled == false, sendFile performed no work.
  17. //
  18. // Note that sendfile for windows does not suppport >2GB file.
  19. func sendFile(fd *netFD, r io.Reader) (written int64, err error, handled bool) {
  20. var n int64 = 0 // by default, copy until EOF
  21. lr, ok := r.(*io.LimitedReader)
  22. if ok {
  23. n, r = lr.N, lr.R
  24. if n <= 0 {
  25. return 0, nil, true
  26. }
  27. }
  28. f, ok := r.(*os.File)
  29. if !ok {
  30. return 0, nil, false
  31. }
  32. if err := fd.writeLock(); err != nil {
  33. return 0, err, true
  34. }
  35. defer fd.writeUnlock()
  36. o := &fd.wop
  37. o.qty = uint32(n)
  38. o.handle = syscall.Handle(f.Fd())
  39. done, err := wsrv.ExecIO(o, "TransmitFile", func(o *operation) error {
  40. return syscall.TransmitFile(o.fd.sysfd, o.handle, o.qty, 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
  41. })
  42. if err != nil {
  43. return 0, err, false
  44. }
  45. if lr != nil {
  46. lr.N -= int64(done)
  47. }
  48. return int64(done), nil, true
  49. }