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