diff options
Diffstat (limited to 'src/net/sendfile_linux.go')
-rw-r--r-- | src/net/sendfile_linux.go | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/src/net/sendfile_linux.go b/src/net/sendfile_linux.go new file mode 100644 index 0000000..e5150aa --- /dev/null +++ b/src/net/sendfile_linux.go @@ -0,0 +1,53 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package net + +import ( + "internal/poll" + "io" + "os" +) + +// sendFile copies the contents of r to c using the sendfile +// system call to minimize copies. +// +// if handled == true, sendFile returns the number of bytes copied and any +// non-EOF error. +// +// if handled == false, sendFile performed no work. +func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) { + var remain int64 = 1 << 62 // by default, copy until EOF + + lr, ok := r.(*io.LimitedReader) + if ok { + remain, r = lr.N, lr.R + if remain <= 0 { + return 0, nil, true + } + } + f, ok := r.(*os.File) + if !ok { + return 0, nil, false + } + + sc, err := f.SyscallConn() + if err != nil { + return 0, nil, false + } + + var werr error + err = sc.Read(func(fd uintptr) bool { + written, werr = poll.SendFile(&c.pfd, int(fd), remain) + return true + }) + if err == nil { + err = werr + } + + if lr != nil { + lr.N = remain - written + } + return written, wrapSyscallError("sendfile", err), written > 0 +} |