gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/sendfile.cc (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <fcntl.h> 16 #include <linux/unistd.h> 17 #include <sys/eventfd.h> 18 #include <sys/sendfile.h> 19 #include <unistd.h> 20 21 #include <string_view> 22 23 #include "gmock/gmock.h" 24 #include "gtest/gtest.h" 25 #include "absl/strings/string_view.h" 26 #include "absl/time/clock.h" 27 #include "absl/time/time.h" 28 #include "test/util/eventfd_util.h" 29 #include "test/util/file_descriptor.h" 30 #include "test/util/signal_util.h" 31 #include "test/util/temp_path.h" 32 #include "test/util/test_util.h" 33 #include "test/util/thread_util.h" 34 #include "test/util/timer_util.h" 35 36 namespace gvisor { 37 namespace testing { 38 39 namespace { 40 41 TEST(SendFileTest, SendZeroBytes) { 42 // Create temp files. 43 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 44 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 45 46 // Open the input file as read only. 47 const FileDescriptor inf = 48 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 49 50 // Open the output file as write only. 51 const FileDescriptor outf = 52 ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 53 54 // Send data and verify that sendfile returns the correct value. 55 EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, 0), 56 SyscallSucceedsWithValue(0)); 57 } 58 59 TEST(SendFileTest, InvalidOffset) { 60 // Create temp files. 61 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 62 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 63 64 // Open the input file as read only. 65 const FileDescriptor inf = 66 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 67 68 // Open the output file as write only. 69 const FileDescriptor outf = 70 ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 71 72 // Send data and verify that sendfile returns the correct value. 73 off_t offset = -1; 74 EXPECT_THAT(sendfile(outf.get(), inf.get(), &offset, 0), 75 SyscallFailsWithErrno(EINVAL)); 76 } 77 78 int memfd_create(const std::string& name, unsigned int flags) { 79 return syscall(__NR_memfd_create, name.c_str(), flags); 80 } 81 82 TEST(SendFileTest, Overflow) { 83 // Create input file. 84 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 85 const FileDescriptor inf = 86 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 87 88 // Open the output file. 89 int fd; 90 EXPECT_THAT(fd = memfd_create("overflow", 0), SyscallSucceeds()); 91 const FileDescriptor outf(fd); 92 93 // out_offset + kSize overflows INT64_MAX. 94 loff_t out_offset = 0x7ffffffffffffffeull; 95 constexpr int kSize = 3; 96 EXPECT_THAT(sendfile(outf.get(), inf.get(), &out_offset, kSize), 97 SyscallFailsWithErrno(EINVAL)); 98 } 99 100 TEST(SendFileTest, SendTrivially) { 101 // Create temp files. 102 constexpr char kData[] = "To be, or not to be, that is the question:"; 103 constexpr int kDataSize = sizeof(kData) - 1; 104 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 105 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 106 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 107 108 // Open the input file as read only. 109 const FileDescriptor inf = 110 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 111 112 // Open the output file as write only. 113 FileDescriptor outf; 114 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 115 116 // Send data and verify that sendfile returns the correct value. 117 int bytes_sent; 118 EXPECT_THAT(bytes_sent = sendfile(outf.get(), inf.get(), nullptr, kDataSize), 119 SyscallSucceedsWithValue(kDataSize)); 120 121 // Close outf to avoid leak. 122 outf.reset(); 123 124 // Open the output file as read only. 125 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY)); 126 127 // Verify that the output file has the correct data. 128 char actual[kDataSize]; 129 ASSERT_THAT(read(outf.get(), &actual, bytes_sent), 130 SyscallSucceedsWithValue(kDataSize)); 131 EXPECT_EQ(kData, absl::string_view(actual, bytes_sent)); 132 } 133 134 TEST(SendFileTest, SendTriviallyWithBothFilesReadWrite) { 135 // Create temp files. 136 constexpr char kData[] = "Whether 'tis nobler in the mind to suffer"; 137 constexpr int kDataSize = sizeof(kData) - 1; 138 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 139 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 140 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 141 142 // Open the input file as readwrite. 143 const FileDescriptor inf = 144 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDWR)); 145 146 // Open the output file as readwrite. 147 FileDescriptor outf; 148 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDWR)); 149 150 // Send data and verify that sendfile returns the correct value. 151 int bytes_sent; 152 EXPECT_THAT(bytes_sent = sendfile(outf.get(), inf.get(), nullptr, kDataSize), 153 SyscallSucceedsWithValue(kDataSize)); 154 155 // Close outf to avoid leak. 156 outf.reset(); 157 158 // Open the output file as read only. 159 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY)); 160 161 // Verify that the output file has the correct data. 162 char actual[kDataSize]; 163 ASSERT_THAT(read(outf.get(), &actual, bytes_sent), 164 SyscallSucceedsWithValue(kDataSize)); 165 EXPECT_EQ(kData, absl::string_view(actual, bytes_sent)); 166 } 167 168 TEST(SendFileTest, SendAndUpdateFileOffset) { 169 // Create temp files. 170 // Test input string length must be > 2 AND even. 171 constexpr char kData[] = "The slings and arrows of outrageous fortune,"; 172 constexpr int kDataSize = sizeof(kData) - 1; 173 constexpr int kHalfDataSize = kDataSize / 2; 174 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 175 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 176 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 177 178 // Open the input file as read only. 179 const FileDescriptor inf = 180 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 181 182 // Open the output file as write only. 183 FileDescriptor outf; 184 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 185 186 // Send data and verify that sendfile returns the correct value. 187 int bytes_sent; 188 EXPECT_THAT( 189 bytes_sent = sendfile(outf.get(), inf.get(), nullptr, kHalfDataSize), 190 SyscallSucceedsWithValue(kHalfDataSize)); 191 192 // Close outf to avoid leak. 193 outf.reset(); 194 195 // Open the output file as read only. 196 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY)); 197 198 // Verify that the output file has the correct data. 199 char actual[kHalfDataSize]; 200 ASSERT_THAT(read(outf.get(), &actual, bytes_sent), 201 SyscallSucceedsWithValue(kHalfDataSize)); 202 EXPECT_EQ(absl::string_view(kData, kHalfDataSize), 203 absl::string_view(actual, bytes_sent)); 204 205 // Verify that the input file offset has been updated. 206 ASSERT_THAT(read(inf.get(), &actual, kDataSize - bytes_sent), 207 SyscallSucceedsWithValue(kHalfDataSize)); 208 EXPECT_EQ( 209 absl::string_view(kData + kDataSize - bytes_sent, kDataSize - bytes_sent), 210 absl::string_view(actual, kHalfDataSize)); 211 } 212 213 TEST(SendFileTest, SendAndUpdateFileOffsetFromNonzeroStartingPoint) { 214 // Create temp files. 215 // Test input string length must be > 2 AND divisible by 4. 216 constexpr char kData[] = "The slings and arrows of outrageous fortune,"; 217 constexpr int kDataSize = sizeof(kData) - 1; 218 constexpr int kHalfDataSize = kDataSize / 2; 219 constexpr int kQuarterDataSize = kHalfDataSize / 2; 220 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 221 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 222 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 223 224 // Open the input file as read only. 225 const FileDescriptor inf = 226 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 227 228 // Open the output file as write only. 229 FileDescriptor outf; 230 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 231 232 // Read a quarter of the data from the infile which should update the file 233 // offset, we don't actually care about the data so it goes into the garbage. 234 char garbage[kQuarterDataSize]; 235 ASSERT_THAT(read(inf.get(), &garbage, kQuarterDataSize), 236 SyscallSucceedsWithValue(kQuarterDataSize)); 237 238 // Send data and verify that sendfile returns the correct value. 239 int bytes_sent; 240 EXPECT_THAT( 241 bytes_sent = sendfile(outf.get(), inf.get(), nullptr, kHalfDataSize), 242 SyscallSucceedsWithValue(kHalfDataSize)); 243 244 // Close out_fd to avoid leak. 245 outf.reset(); 246 247 // Open the output file as read only. 248 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY)); 249 250 // Verify that the output file has the correct data. 251 char actual[kHalfDataSize]; 252 ASSERT_THAT(read(outf.get(), &actual, bytes_sent), 253 SyscallSucceedsWithValue(kHalfDataSize)); 254 EXPECT_EQ(absl::string_view(kData + kQuarterDataSize, kHalfDataSize), 255 absl::string_view(actual, bytes_sent)); 256 257 // Verify that the input file offset has been updated. 258 ASSERT_THAT(read(inf.get(), &actual, kQuarterDataSize), 259 SyscallSucceedsWithValue(kQuarterDataSize)); 260 261 EXPECT_EQ( 262 absl::string_view(kData + kDataSize - kQuarterDataSize, kQuarterDataSize), 263 absl::string_view(actual, kQuarterDataSize)); 264 } 265 266 TEST(SendFileTest, SendAndUpdateGivenOffset) { 267 // Create temp files. 268 // Test input string length must be >= 4 AND divisible by 4. 269 constexpr char kData[] = "Or to take Arms against a Sea of troubles,"; 270 constexpr int kDataSize = sizeof(kData) + 1; 271 constexpr int kHalfDataSize = kDataSize / 2; 272 constexpr int kQuarterDataSize = kHalfDataSize / 2; 273 constexpr int kThreeFourthsDataSize = 3 * kDataSize / 4; 274 275 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 276 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 277 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 278 279 // Open the input file as read only. 280 const FileDescriptor inf = 281 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 282 283 // Open the output file as write only. 284 FileDescriptor outf; 285 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 286 287 // Create offset for sending. 288 off_t offset = kQuarterDataSize; 289 290 // Send data and verify that sendfile returns the correct value. 291 int bytes_sent; 292 EXPECT_THAT( 293 bytes_sent = sendfile(outf.get(), inf.get(), &offset, kHalfDataSize), 294 SyscallSucceedsWithValue(kHalfDataSize)); 295 296 // Close out_fd to avoid leak. 297 outf.reset(); 298 299 // Open the output file as read only. 300 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY)); 301 302 // Verify that the output file has the correct data. 303 char actual[kHalfDataSize]; 304 ASSERT_THAT(read(outf.get(), &actual, bytes_sent), 305 SyscallSucceedsWithValue(kHalfDataSize)); 306 EXPECT_EQ(absl::string_view(kData + kQuarterDataSize, kHalfDataSize), 307 absl::string_view(actual, bytes_sent)); 308 309 // Verify that the input file offset has NOT been updated. 310 ASSERT_THAT(read(inf.get(), &actual, kHalfDataSize), 311 SyscallSucceedsWithValue(kHalfDataSize)); 312 EXPECT_EQ(absl::string_view(kData, kHalfDataSize), 313 absl::string_view(actual, kHalfDataSize)); 314 315 // Verify that the offset pointer has been updated. 316 EXPECT_EQ(offset, kThreeFourthsDataSize); 317 } 318 319 TEST(SendFileTest, DoNotSendfileIfOutfileIsAppendOnly) { 320 // Create temp files. 321 constexpr char kData[] = "And by opposing end them: to die, to sleep"; 322 constexpr int kDataSize = sizeof(kData) - 1; 323 324 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 325 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 326 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 327 328 // Open the input file as read only. 329 const FileDescriptor inf = 330 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 331 332 // Open the output file as append only. 333 const FileDescriptor outf = 334 ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY | O_APPEND)); 335 336 // Send data and verify that sendfile returns the correct errno. 337 EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, kDataSize), 338 SyscallFailsWithErrno(EINVAL)); 339 } 340 341 TEST(SendFileTest, AppendCheckOrdering) { 342 constexpr char kData[] = "And by opposing end them: to die, to sleep"; 343 constexpr int kDataSize = sizeof(kData) - 1; 344 const TempPath file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 345 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 346 347 const FileDescriptor read = 348 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDONLY)); 349 const FileDescriptor write = 350 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_WRONLY)); 351 const FileDescriptor append = 352 ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_APPEND)); 353 354 // Check that read/write file mode is verified before append. 355 EXPECT_THAT(sendfile(append.get(), read.get(), nullptr, kDataSize), 356 SyscallFailsWithErrno(EBADF)); 357 EXPECT_THAT(sendfile(write.get(), write.get(), nullptr, kDataSize), 358 SyscallFailsWithErrno(EBADF)); 359 } 360 361 TEST(SendFileTest, DoNotSendfileIfOutfileIsNotWritable) { 362 // Create temp files. 363 constexpr char kData[] = "No more; and by a sleep, to say we end"; 364 constexpr int kDataSize = sizeof(kData) - 1; 365 366 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 367 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 368 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 369 370 // Open the input file as read only. 371 const FileDescriptor inf = 372 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 373 374 // Open the output file as read only. 375 const FileDescriptor outf = 376 ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY)); 377 378 // Send data and verify that sendfile returns the correct errno. 379 EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, kDataSize), 380 SyscallFailsWithErrno(EBADF)); 381 } 382 383 TEST(SendFileTest, DoNotSendfileIfInfileIsNotReadable) { 384 // Create temp files. 385 constexpr char kData[] = "the heart-ache, and the thousand natural shocks"; 386 constexpr int kDataSize = sizeof(kData) - 1; 387 388 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 389 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 390 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 391 392 // Open the input file as write only. 393 const FileDescriptor inf = 394 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_WRONLY)); 395 396 // Open the output file as write only. 397 const FileDescriptor outf = 398 ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 399 400 // Send data and verify that sendfile returns the correct errno. 401 EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, kDataSize), 402 SyscallFailsWithErrno(EBADF)); 403 } 404 405 TEST(SendFileTest, DoNotSendANegativeNumberOfBytes) { 406 // Create temp files. 407 constexpr char kData[] = "that Flesh is heir to? 'Tis a consummation"; 408 409 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 410 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 411 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 412 413 // Open the input file as read only. 414 const FileDescriptor inf = 415 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 416 417 // Open the output file as write only. 418 const FileDescriptor outf = 419 ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 420 421 // Send data and verify that sendfile returns the correct errno. 422 EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, -1), 423 SyscallFailsWithErrno(EINVAL)); 424 } 425 426 TEST(SendFileTest, SendTheCorrectNumberOfBytesEvenIfWeTryToSendTooManyBytes) { 427 // Create temp files. 428 constexpr char kData[] = "devoutly to be wished. To die, to sleep,"; 429 constexpr int kDataSize = sizeof(kData) - 1; 430 431 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 432 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 433 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 434 435 // Open the input file as read only. 436 const FileDescriptor inf = 437 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 438 439 // Open the output file as write only. 440 FileDescriptor outf; 441 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 442 443 // Send data and verify that sendfile returns the correct value. 444 int bytes_sent; 445 EXPECT_THAT( 446 bytes_sent = sendfile(outf.get(), inf.get(), nullptr, kDataSize + 100), 447 SyscallSucceedsWithValue(kDataSize)); 448 449 // Close outf to avoid leak. 450 outf.reset(); 451 452 // Open the output file as read only. 453 outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY)); 454 455 // Verify that the output file has the correct data. 456 char actual[kDataSize]; 457 ASSERT_THAT(read(outf.get(), &actual, bytes_sent), 458 SyscallSucceedsWithValue(kDataSize)); 459 EXPECT_EQ(kData, absl::string_view(actual, bytes_sent)); 460 } 461 462 TEST(SendFileTest, SendToNotARegularFile) { 463 // Make temp input directory and open as read only. 464 const TempPath dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 465 const FileDescriptor inf = 466 ASSERT_NO_ERRNO_AND_VALUE(Open(dir.path(), O_RDONLY)); 467 468 // Make temp output file and open as write only. 469 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 470 const FileDescriptor outf = 471 ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 472 473 // Receive an error since a directory is not a regular file. 474 EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, 1), 475 SyscallFailsWithErrno(EINVAL)); 476 } 477 478 TEST(SendFileTest, SendPipeWouldBlock) { 479 // This test fails on Linux, likely due to a Linux bug. 480 SKIP_IF(!IsRunningOnGvisor()); 481 // Create temp file. 482 constexpr char kData[] = 483 "The fool doth think he is wise, but the wise man knows himself to be a " 484 "fool."; 485 constexpr int kDataSize = sizeof(kData) - 1; 486 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 487 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 488 489 // Open the input file as read only. 490 const FileDescriptor inf = 491 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 492 493 // Setup the output named pipe. 494 int fds[2]; 495 ASSERT_THAT(pipe2(fds, O_NONBLOCK), SyscallSucceeds()); 496 const FileDescriptor rfd(fds[0]); 497 const FileDescriptor wfd(fds[1]); 498 499 // Fill up the pipe's buffer. 500 int pipe_size = -1; 501 ASSERT_THAT(pipe_size = fcntl(wfd.get(), F_GETPIPE_SZ), SyscallSucceeds()); 502 std::vector<char> buf(2 * pipe_size); 503 ASSERT_THAT(write(wfd.get(), buf.data(), buf.size()), 504 SyscallSucceedsWithValue(pipe_size)); 505 506 EXPECT_THAT(sendfile(wfd.get(), inf.get(), nullptr, kDataSize), 507 SyscallFailsWithErrno(EWOULDBLOCK)); 508 } 509 510 TEST(SendFileTest, SendPipeEOF) { 511 // Create and open an empty input file. 512 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 513 const FileDescriptor inf = 514 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 515 516 // Setup the output named pipe. 517 int fds[2]; 518 ASSERT_THAT(pipe2(fds, O_NONBLOCK), SyscallSucceeds()); 519 const FileDescriptor rfd(fds[0]); 520 const FileDescriptor wfd(fds[1]); 521 522 EXPECT_THAT(sendfile(wfd.get(), inf.get(), nullptr, 123), 523 SyscallSucceedsWithValue(0)); 524 } 525 526 TEST(SendFileTest, SendToFullPipeReturnsEAGAIN) { 527 // This test fails on Linux, likely due to a Linux bug. 528 SKIP_IF(!IsRunningOnGvisor()); 529 // Create and open an empty input file. 530 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 531 const FileDescriptor in_fd = 532 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDWR)); 533 534 // Set up the output pipe. 535 int fds[2]; 536 ASSERT_THAT(pipe2(fds, O_NONBLOCK), SyscallSucceeds()); 537 const FileDescriptor rfd(fds[0]); 538 const FileDescriptor wfd(fds[1]); 539 540 int pipe_size = -1; 541 ASSERT_THAT(pipe_size = fcntl(wfd.get(), F_GETPIPE_SZ), SyscallSucceeds()); 542 int data_size = pipe_size * 8; 543 ASSERT_THAT(ftruncate(in_fd.get(), data_size), SyscallSucceeds()); 544 545 ASSERT_THAT(sendfile(wfd.get(), in_fd.get(), 0, data_size), 546 SyscallSucceeds()); 547 EXPECT_THAT(sendfile(wfd.get(), in_fd.get(), 0, data_size), 548 SyscallFailsWithErrno(EAGAIN)); 549 } 550 551 TEST(SendFileTest, SendPipeBlocks) { 552 // Create temp file. 553 constexpr char kData[] = 554 "The fault, dear Brutus, is not in our stars, but in ourselves."; 555 constexpr int kDataSize = sizeof(kData) - 1; 556 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 557 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 558 559 // Open the input file as read only. 560 const FileDescriptor inf = 561 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 562 563 // Setup the output named pipe. 564 int fds[2]; 565 ASSERT_THAT(pipe(fds), SyscallSucceeds()); 566 const FileDescriptor rfd(fds[0]); 567 const FileDescriptor wfd(fds[1]); 568 569 // Fill up the pipe's buffer. 570 int pipe_size = -1; 571 ASSERT_THAT(pipe_size = fcntl(wfd.get(), F_GETPIPE_SZ), SyscallSucceeds()); 572 std::vector<char> buf(pipe_size); 573 ASSERT_THAT(write(wfd.get(), buf.data(), buf.size()), 574 SyscallSucceedsWithValue(pipe_size)); 575 576 ScopedThread t([&]() { 577 absl::SleepFor(absl::Milliseconds(100)); 578 ASSERT_THAT(read(rfd.get(), buf.data(), buf.size()), 579 SyscallSucceedsWithValue(pipe_size)); 580 }); 581 582 EXPECT_THAT(sendfile(wfd.get(), inf.get(), nullptr, kDataSize), 583 SyscallSucceedsWithValue(kDataSize)); 584 } 585 586 TEST(SendFileTest, SendFileToPipe) { 587 // Create temp file. 588 constexpr char kData[] = "<insert-quote-here>"; 589 constexpr int kDataSize = sizeof(kData) - 1; 590 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 591 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 592 const FileDescriptor inf = 593 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 594 595 // Create a pipe for sending to a pipe. 596 int fds[2]; 597 ASSERT_THAT(pipe(fds), SyscallSucceeds()); 598 const FileDescriptor rfd(fds[0]); 599 const FileDescriptor wfd(fds[1]); 600 601 // Expect to read up to the given size. 602 std::vector<char> buf(kDataSize); 603 ScopedThread t([&]() { 604 absl::SleepFor(absl::Milliseconds(100)); 605 ASSERT_THAT(read(rfd.get(), buf.data(), buf.size()), 606 SyscallSucceedsWithValue(kDataSize)); 607 }); 608 609 // Send with twice the size of the file, which should hit EOF. 610 EXPECT_THAT(sendfile(wfd.get(), inf.get(), nullptr, kDataSize * 2), 611 SyscallSucceedsWithValue(kDataSize)); 612 } 613 614 TEST(SendFileTest, SendFileToSelf) { 615 int rawfd; 616 ASSERT_THAT(rawfd = memfd_create("memfd", 0), SyscallSucceeds()); 617 const FileDescriptor fd(rawfd); 618 619 char c = 0x01; 620 ASSERT_THAT(WriteFd(fd.get(), &c, 1), SyscallSucceedsWithValue(1)); 621 622 // Arbitrarily chosen to make sendfile() take long enough that the sentry 623 // watchdog usually fires unless it's reset by sendfile() between iterations 624 // of the buffered copy. See b/172076632. 625 constexpr size_t kSendfileSize = 0xa00000; 626 627 off_t offset = 0; 628 ASSERT_THAT(sendfile(fd.get(), fd.get(), &offset, kSendfileSize), 629 SyscallSucceedsWithValue(kSendfileSize)); 630 } 631 632 // NOTE(b/237442794): Regression test. Make sure sendfile works with a count 633 // larger than input file size. 634 TEST(SendFileTest, LargeCount) { 635 // Create input file with some wisdom. It is imperative to use a 636 // Shakespearean quote, consistent with the rest of this file. 637 constexpr absl::string_view kData = 638 "We know what we are, but know not what we may be."; 639 const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 640 GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode)); 641 642 const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile()); 643 644 // Open the input file as read only. 645 const FileDescriptor inf = 646 ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY)); 647 648 // Open the output file as write only. 649 const FileDescriptor outf = 650 ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY)); 651 652 // Set a count larger than kDataSize. 653 EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, 2 * kData.size()), 654 SyscallSucceedsWithValue(kData.size())); 655 } 656 657 } // namespace 658 659 } // namespace testing 660 } // namespace gvisor