diff options
-rw-r--r-- | pkg/tcpip/transport/tcp/endpoint.go | 5 | ||||
-rw-r--r-- | test/syscalls/linux/BUILD | 1 | ||||
-rw-r--r-- | test/syscalls/linux/socket_ip_tcp_generic.cc | 23 |
3 files changed, 27 insertions, 2 deletions
diff --git a/pkg/tcpip/transport/tcp/endpoint.go b/pkg/tcpip/transport/tcp/endpoint.go index 83ec99fa9..f47b39ccc 100644 --- a/pkg/tcpip/transport/tcp/endpoint.go +++ b/pkg/tcpip/transport/tcp/endpoint.go @@ -1552,10 +1552,11 @@ func (e *endpoint) Write(p tcpip.Payloader, opts tcpip.WriteOptions) (int64, tcp return nil, nil } v := make([]byte, avail) - if _, err := io.ReadFull(p, v); err != nil { + n, err := p.Read(v) + if err != nil && err != io.EOF { return nil, &tcpip.ErrBadBuffer{} } - return v, nil + return v[:n], nil }() if len(v) == 0 || err != nil { return nil, 0, err diff --git a/test/syscalls/linux/BUILD b/test/syscalls/linux/BUILD index f871426f0..5371f825c 100644 --- a/test/syscalls/linux/BUILD +++ b/test/syscalls/linux/BUILD @@ -2384,6 +2384,7 @@ cc_library( "@com_google_absl//absl/memory", "@com_google_absl//absl/time", gtest, + "//test/util:temp_path", "//test/util:test_util", "//test/util:thread_util", ], diff --git a/test/syscalls/linux/socket_ip_tcp_generic.cc b/test/syscalls/linux/socket_ip_tcp_generic.cc index 579e824cd..f10f55b27 100644 --- a/test/syscalls/linux/socket_ip_tcp_generic.cc +++ b/test/syscalls/linux/socket_ip_tcp_generic.cc @@ -29,6 +29,7 @@ #include "absl/time/clock.h" #include "absl/time/time.h" #include "test/syscalls/linux/socket_test_util.h" +#include "test/util/temp_path.h" #include "test/util/test_util.h" #include "test/util/thread_util.h" @@ -1059,6 +1060,28 @@ TEST_P(TCPSocketPairTest, SpliceToPipe) { SyscallSucceedsWithValue(buf.size())); EXPECT_EQ(memcmp(rbuf.data(), buf.data(), buf.size()), 0); } + +#include <sys/sendfile.h> + +TEST_P(TCPSocketPairTest, SendfileFromRegularFileSucceeds) { + auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); + const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); + const FileDescriptor in_fd = + ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDWR)); + // Fill with some random data. + std::vector<char> buf(kPageSize / 2); + RandomizeBuffer(buf.data(), buf.size()); + ASSERT_THAT(pwrite(in_fd.get(), buf.data(), buf.size(), 0), + SyscallSucceedsWithValue(buf.size())); + + EXPECT_THAT( + sendfile(sockets->first_fd(), in_fd.get(), nullptr, buf.size() + 1), + SyscallSucceedsWithValue(buf.size())); + std::vector<char> rbuf(buf.size() + 1); + ASSERT_THAT(read(sockets->second_fd(), rbuf.data(), rbuf.size()), + SyscallSucceedsWithValue(buf.size())); + EXPECT_EQ(memcmp(rbuf.data(), buf.data(), buf.size()), 0); +} #endif // __linux__ TEST_P(TCPSocketPairTest, SetTCPWindowClampBelowMinRcvBufConnectedSocket) { |