github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/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 "gmock/gmock.h"
    22  #include "gtest/gtest.h"
    23  #include "absl/strings/string_view.h"
    24  #include "absl/time/clock.h"
    25  #include "absl/time/time.h"
    26  #include "test/util/eventfd_util.h"
    27  #include "test/util/file_descriptor.h"
    28  #include "test/util/signal_util.h"
    29  #include "test/util/temp_path.h"
    30  #include "test/util/test_util.h"
    31  #include "test/util/thread_util.h"
    32  #include "test/util/timer_util.h"
    33  
    34  namespace gvisor {
    35  namespace testing {
    36  
    37  namespace {
    38  
    39  TEST(SendFileTest, SendZeroBytes) {
    40    // Create temp files.
    41    const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
    42    const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
    43  
    44    // Open the input file as read only.
    45    const FileDescriptor inf =
    46        ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY));
    47  
    48    // Open the output file as write only.
    49    const FileDescriptor outf =
    50        ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY));
    51  
    52    // Send data and verify that sendfile returns the correct value.
    53    EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, 0),
    54                SyscallSucceedsWithValue(0));
    55  }
    56  
    57  TEST(SendFileTest, InvalidOffset) {
    58    // Create temp files.
    59    const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
    60    const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
    61  
    62    // Open the input file as read only.
    63    const FileDescriptor inf =
    64        ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY));
    65  
    66    // Open the output file as write only.
    67    const FileDescriptor outf =
    68        ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY));
    69  
    70    // Send data and verify that sendfile returns the correct value.
    71    off_t offset = -1;
    72    EXPECT_THAT(sendfile(outf.get(), inf.get(), &offset, 0),
    73                SyscallFailsWithErrno(EINVAL));
    74  }
    75  
    76  int memfd_create(const std::string& name, unsigned int flags) {
    77    return syscall(__NR_memfd_create, name.c_str(), flags);
    78  }
    79  
    80  TEST(SendFileTest, Overflow) {
    81    // Create input file.
    82    const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
    83    const FileDescriptor inf =
    84        ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY));
    85  
    86    // Open the output file.
    87    int fd;
    88    EXPECT_THAT(fd = memfd_create("overflow", 0), SyscallSucceeds());
    89    const FileDescriptor outf(fd);
    90  
    91    // out_offset + kSize overflows INT64_MAX.
    92    loff_t out_offset = 0x7ffffffffffffffeull;
    93    constexpr int kSize = 3;
    94    EXPECT_THAT(sendfile(outf.get(), inf.get(), &out_offset, kSize),
    95                SyscallFailsWithErrno(EINVAL));
    96  }
    97  
    98  TEST(SendFileTest, SendTrivially) {
    99    // Create temp files.
   100    constexpr char kData[] = "To be, or not to be, that is the question:";
   101    constexpr int kDataSize = sizeof(kData) - 1;
   102    const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith(
   103        GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode));
   104    const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
   105  
   106    // Open the input file as read only.
   107    const FileDescriptor inf =
   108        ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY));
   109  
   110    // Open the output file as write only.
   111    FileDescriptor outf;
   112    outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY));
   113  
   114    // Send data and verify that sendfile returns the correct value.
   115    int bytes_sent;
   116    EXPECT_THAT(bytes_sent = sendfile(outf.get(), inf.get(), nullptr, kDataSize),
   117                SyscallSucceedsWithValue(kDataSize));
   118  
   119    // Close outf to avoid leak.
   120    outf.reset();
   121  
   122    // Open the output file as read only.
   123    outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY));
   124  
   125    // Verify that the output file has the correct data.
   126    char actual[kDataSize];
   127    ASSERT_THAT(read(outf.get(), &actual, bytes_sent),
   128                SyscallSucceedsWithValue(kDataSize));
   129    EXPECT_EQ(kData, absl::string_view(actual, bytes_sent));
   130  }
   131  
   132  TEST(SendFileTest, SendTriviallyWithBothFilesReadWrite) {
   133    // Create temp files.
   134    constexpr char kData[] = "Whether 'tis nobler in the mind to suffer";
   135    constexpr int kDataSize = sizeof(kData) - 1;
   136    const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith(
   137        GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode));
   138    const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
   139  
   140    // Open the input file as readwrite.
   141    const FileDescriptor inf =
   142        ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDWR));
   143  
   144    // Open the output file as readwrite.
   145    FileDescriptor outf;
   146    outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDWR));
   147  
   148    // Send data and verify that sendfile returns the correct value.
   149    int bytes_sent;
   150    EXPECT_THAT(bytes_sent = sendfile(outf.get(), inf.get(), nullptr, kDataSize),
   151                SyscallSucceedsWithValue(kDataSize));
   152  
   153    // Close outf to avoid leak.
   154    outf.reset();
   155  
   156    // Open the output file as read only.
   157    outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY));
   158  
   159    // Verify that the output file has the correct data.
   160    char actual[kDataSize];
   161    ASSERT_THAT(read(outf.get(), &actual, bytes_sent),
   162                SyscallSucceedsWithValue(kDataSize));
   163    EXPECT_EQ(kData, absl::string_view(actual, bytes_sent));
   164  }
   165  
   166  TEST(SendFileTest, SendAndUpdateFileOffset) {
   167    // Create temp files.
   168    // Test input string length must be > 2 AND even.
   169    constexpr char kData[] = "The slings and arrows of outrageous fortune,";
   170    constexpr int kDataSize = sizeof(kData) - 1;
   171    constexpr int kHalfDataSize = kDataSize / 2;
   172    const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith(
   173        GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode));
   174    const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
   175  
   176    // Open the input file as read only.
   177    const FileDescriptor inf =
   178        ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY));
   179  
   180    // Open the output file as write only.
   181    FileDescriptor outf;
   182    outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY));
   183  
   184    // Send data and verify that sendfile returns the correct value.
   185    int bytes_sent;
   186    EXPECT_THAT(
   187        bytes_sent = sendfile(outf.get(), inf.get(), nullptr, kHalfDataSize),
   188        SyscallSucceedsWithValue(kHalfDataSize));
   189  
   190    // Close outf to avoid leak.
   191    outf.reset();
   192  
   193    // Open the output file as read only.
   194    outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY));
   195  
   196    // Verify that the output file has the correct data.
   197    char actual[kHalfDataSize];
   198    ASSERT_THAT(read(outf.get(), &actual, bytes_sent),
   199                SyscallSucceedsWithValue(kHalfDataSize));
   200    EXPECT_EQ(absl::string_view(kData, kHalfDataSize),
   201              absl::string_view(actual, bytes_sent));
   202  
   203    // Verify that the input file offset has been updated.
   204    ASSERT_THAT(read(inf.get(), &actual, kDataSize - bytes_sent),
   205                SyscallSucceedsWithValue(kHalfDataSize));
   206    EXPECT_EQ(
   207        absl::string_view(kData + kDataSize - bytes_sent, kDataSize - bytes_sent),
   208        absl::string_view(actual, kHalfDataSize));
   209  }
   210  
   211  TEST(SendFileTest, SendToDevZeroAndUpdateFileOffset) {
   212    // Create temp files.
   213    // Test input string length must be > 2 AND even.
   214    constexpr char kData[] = "The slings and arrows of outrageous fortune,";
   215    constexpr int kDataSize = sizeof(kData) - 1;
   216    constexpr int kHalfDataSize = kDataSize / 2;
   217    const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith(
   218        GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode));
   219  
   220    // Open the input file as read only.
   221    const FileDescriptor inf =
   222        ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY));
   223  
   224    // Open /dev/zero as write only.
   225    const FileDescriptor outf =
   226        ASSERT_NO_ERRNO_AND_VALUE(Open("/dev/zero", O_WRONLY));
   227  
   228    // Send data and verify that sendfile returns the correct value.
   229    int bytes_sent;
   230    EXPECT_THAT(
   231        bytes_sent = sendfile(outf.get(), inf.get(), nullptr, kHalfDataSize),
   232        SyscallSucceedsWithValue(kHalfDataSize));
   233  
   234    char actual[kHalfDataSize];
   235    // Verify that the input file offset has been updated.
   236    ASSERT_THAT(read(inf.get(), &actual, kDataSize - bytes_sent),
   237                SyscallSucceedsWithValue(kHalfDataSize));
   238    EXPECT_EQ(
   239        absl::string_view(kData + kDataSize - bytes_sent, kDataSize - bytes_sent),
   240        absl::string_view(actual, kHalfDataSize));
   241  }
   242  
   243  TEST(SendFileTest, SendAndUpdateFileOffsetFromNonzeroStartingPoint) {
   244    // Create temp files.
   245    // Test input string length must be > 2 AND divisible by 4.
   246    constexpr char kData[] = "The slings and arrows of outrageous fortune,";
   247    constexpr int kDataSize = sizeof(kData) - 1;
   248    constexpr int kHalfDataSize = kDataSize / 2;
   249    constexpr int kQuarterDataSize = kHalfDataSize / 2;
   250    const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith(
   251        GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode));
   252    const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
   253  
   254    // Open the input file as read only.
   255    const FileDescriptor inf =
   256        ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY));
   257  
   258    // Open the output file as write only.
   259    FileDescriptor outf;
   260    outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY));
   261  
   262    // Read a quarter of the data from the infile which should update the file
   263    // offset, we don't actually care about the data so it goes into the garbage.
   264    char garbage[kQuarterDataSize];
   265    ASSERT_THAT(read(inf.get(), &garbage, kQuarterDataSize),
   266                SyscallSucceedsWithValue(kQuarterDataSize));
   267  
   268    // Send data and verify that sendfile returns the correct value.
   269    int bytes_sent;
   270    EXPECT_THAT(
   271        bytes_sent = sendfile(outf.get(), inf.get(), nullptr, kHalfDataSize),
   272        SyscallSucceedsWithValue(kHalfDataSize));
   273  
   274    // Close out_fd to avoid leak.
   275    outf.reset();
   276  
   277    // Open the output file as read only.
   278    outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY));
   279  
   280    // Verify that the output file has the correct data.
   281    char actual[kHalfDataSize];
   282    ASSERT_THAT(read(outf.get(), &actual, bytes_sent),
   283                SyscallSucceedsWithValue(kHalfDataSize));
   284    EXPECT_EQ(absl::string_view(kData + kQuarterDataSize, kHalfDataSize),
   285              absl::string_view(actual, bytes_sent));
   286  
   287    // Verify that the input file offset has been updated.
   288    ASSERT_THAT(read(inf.get(), &actual, kQuarterDataSize),
   289                SyscallSucceedsWithValue(kQuarterDataSize));
   290  
   291    EXPECT_EQ(
   292        absl::string_view(kData + kDataSize - kQuarterDataSize, kQuarterDataSize),
   293        absl::string_view(actual, kQuarterDataSize));
   294  }
   295  
   296  TEST(SendFileTest, SendAndUpdateGivenOffset) {
   297    // Create temp files.
   298    // Test input string length must be >= 4 AND divisible by 4.
   299    constexpr char kData[] = "Or to take Arms against a Sea of troubles,";
   300    constexpr int kDataSize = sizeof(kData) + 1;
   301    constexpr int kHalfDataSize = kDataSize / 2;
   302    constexpr int kQuarterDataSize = kHalfDataSize / 2;
   303    constexpr int kThreeFourthsDataSize = 3 * kDataSize / 4;
   304  
   305    const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith(
   306        GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode));
   307    const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
   308  
   309    // Open the input file as read only.
   310    const FileDescriptor inf =
   311        ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY));
   312  
   313    // Open the output file as write only.
   314    FileDescriptor outf;
   315    outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY));
   316  
   317    // Create offset for sending.
   318    off_t offset = kQuarterDataSize;
   319  
   320    // Send data and verify that sendfile returns the correct value.
   321    int bytes_sent;
   322    EXPECT_THAT(
   323        bytes_sent = sendfile(outf.get(), inf.get(), &offset, kHalfDataSize),
   324        SyscallSucceedsWithValue(kHalfDataSize));
   325  
   326    // Close out_fd to avoid leak.
   327    outf.reset();
   328  
   329    // Open the output file as read only.
   330    outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY));
   331  
   332    // Verify that the output file has the correct data.
   333    char actual[kHalfDataSize];
   334    ASSERT_THAT(read(outf.get(), &actual, bytes_sent),
   335                SyscallSucceedsWithValue(kHalfDataSize));
   336    EXPECT_EQ(absl::string_view(kData + kQuarterDataSize, kHalfDataSize),
   337              absl::string_view(actual, bytes_sent));
   338  
   339    // Verify that the input file offset has NOT been updated.
   340    ASSERT_THAT(read(inf.get(), &actual, kHalfDataSize),
   341                SyscallSucceedsWithValue(kHalfDataSize));
   342    EXPECT_EQ(absl::string_view(kData, kHalfDataSize),
   343              absl::string_view(actual, kHalfDataSize));
   344  
   345    // Verify that the offset pointer has been updated.
   346    EXPECT_EQ(offset, kThreeFourthsDataSize);
   347  }
   348  
   349  TEST(SendFileTest, DoNotSendfileIfOutfileIsAppendOnly) {
   350    // Create temp files.
   351    constexpr char kData[] = "And by opposing end them: to die, to sleep";
   352    constexpr int kDataSize = sizeof(kData) - 1;
   353  
   354    const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith(
   355        GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode));
   356    const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
   357  
   358    // Open the input file as read only.
   359    const FileDescriptor inf =
   360        ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY));
   361  
   362    // Open the output file as append only.
   363    const FileDescriptor outf =
   364        ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY | O_APPEND));
   365  
   366    // Send data and verify that sendfile returns the correct errno.
   367    EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, kDataSize),
   368                SyscallFailsWithErrno(EINVAL));
   369  }
   370  
   371  TEST(SendFileTest, AppendCheckOrdering) {
   372    constexpr char kData[] = "And by opposing end them: to die, to sleep";
   373    constexpr int kDataSize = sizeof(kData) - 1;
   374    const TempPath file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith(
   375        GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode));
   376  
   377    const FileDescriptor read =
   378        ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDONLY));
   379    const FileDescriptor write =
   380        ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_WRONLY));
   381    const FileDescriptor append =
   382        ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_APPEND));
   383  
   384    // Check that read/write file mode is verified before append.
   385    EXPECT_THAT(sendfile(append.get(), read.get(), nullptr, kDataSize),
   386                SyscallFailsWithErrno(EBADF));
   387    EXPECT_THAT(sendfile(write.get(), write.get(), nullptr, kDataSize),
   388                SyscallFailsWithErrno(EBADF));
   389  }
   390  
   391  TEST(SendFileTest, DoNotSendfileIfOutfileIsNotWritable) {
   392    // Create temp files.
   393    constexpr char kData[] = "No more; and by a sleep, to say we end";
   394    constexpr int kDataSize = sizeof(kData) - 1;
   395  
   396    const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith(
   397        GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode));
   398    const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
   399  
   400    // Open the input file as read only.
   401    const FileDescriptor inf =
   402        ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY));
   403  
   404    // Open the output file as read only.
   405    const FileDescriptor outf =
   406        ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY));
   407  
   408    // Send data and verify that sendfile returns the correct errno.
   409    EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, kDataSize),
   410                SyscallFailsWithErrno(EBADF));
   411  }
   412  
   413  TEST(SendFileTest, DoNotSendfileIfInfileIsNotReadable) {
   414    // Create temp files.
   415    constexpr char kData[] = "the heart-ache, and the thousand natural shocks";
   416    constexpr int kDataSize = sizeof(kData) - 1;
   417  
   418    const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith(
   419        GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode));
   420    const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
   421  
   422    // Open the input file as write only.
   423    const FileDescriptor inf =
   424        ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_WRONLY));
   425  
   426    // Open the output file as write only.
   427    const FileDescriptor outf =
   428        ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY));
   429  
   430    // Send data and verify that sendfile returns the correct errno.
   431    EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, kDataSize),
   432                SyscallFailsWithErrno(EBADF));
   433  }
   434  
   435  TEST(SendFileTest, DoNotSendANegativeNumberOfBytes) {
   436    // Create temp files.
   437    constexpr char kData[] = "that Flesh is heir to? 'Tis a consummation";
   438  
   439    const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith(
   440        GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode));
   441    const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
   442  
   443    // Open the input file as read only.
   444    const FileDescriptor inf =
   445        ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY));
   446  
   447    // Open the output file as write only.
   448    const FileDescriptor outf =
   449        ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY));
   450  
   451    // Send data and verify that sendfile returns the correct errno.
   452    EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, -1),
   453                SyscallFailsWithErrno(EINVAL));
   454  }
   455  
   456  TEST(SendFileTest, SendTheCorrectNumberOfBytesEvenIfWeTryToSendTooManyBytes) {
   457    // Create temp files.
   458    constexpr char kData[] = "devoutly to be wished. To die, to sleep,";
   459    constexpr int kDataSize = sizeof(kData) - 1;
   460  
   461    const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith(
   462        GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode));
   463    const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
   464  
   465    // Open the input file as read only.
   466    const FileDescriptor inf =
   467        ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY));
   468  
   469    // Open the output file as write only.
   470    FileDescriptor outf;
   471    outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY));
   472  
   473    // Send data and verify that sendfile returns the correct value.
   474    int bytes_sent;
   475    EXPECT_THAT(
   476        bytes_sent = sendfile(outf.get(), inf.get(), nullptr, kDataSize + 100),
   477        SyscallSucceedsWithValue(kDataSize));
   478  
   479    // Close outf to avoid leak.
   480    outf.reset();
   481  
   482    // Open the output file as read only.
   483    outf = ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_RDONLY));
   484  
   485    // Verify that the output file has the correct data.
   486    char actual[kDataSize];
   487    ASSERT_THAT(read(outf.get(), &actual, bytes_sent),
   488                SyscallSucceedsWithValue(kDataSize));
   489    EXPECT_EQ(kData, absl::string_view(actual, bytes_sent));
   490  }
   491  
   492  TEST(SendFileTest, SendToNotARegularFile) {
   493    // Make temp input directory and open as read only.
   494    const TempPath dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
   495    const FileDescriptor inf =
   496        ASSERT_NO_ERRNO_AND_VALUE(Open(dir.path(), O_RDONLY));
   497  
   498    // Make temp output file and open as write only.
   499    const TempPath out_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
   500    const FileDescriptor outf =
   501        ASSERT_NO_ERRNO_AND_VALUE(Open(out_file.path(), O_WRONLY));
   502  
   503    // Receive an error since a directory is not a regular file.
   504    EXPECT_THAT(sendfile(outf.get(), inf.get(), nullptr, 0),
   505                SyscallFailsWithErrno(EINVAL));
   506  }
   507  
   508  TEST(SendFileTest, SendPipeWouldBlock) {
   509    // Create temp file.
   510    constexpr char kData[] =
   511        "The fool doth think he is wise, but the wise man knows himself to be a "
   512        "fool.";
   513    constexpr int kDataSize = sizeof(kData) - 1;
   514    const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith(
   515        GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode));
   516  
   517    // Open the input file as read only.
   518    const FileDescriptor inf =
   519        ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY));
   520  
   521    // Setup the output named pipe.
   522    int fds[2];
   523    ASSERT_THAT(pipe2(fds, O_NONBLOCK), SyscallSucceeds());
   524    const FileDescriptor rfd(fds[0]);
   525    const FileDescriptor wfd(fds[1]);
   526  
   527    // Fill up the pipe's buffer.
   528    int pipe_size = -1;
   529    ASSERT_THAT(pipe_size = fcntl(wfd.get(), F_GETPIPE_SZ), SyscallSucceeds());
   530    std::vector<char> buf(2 * pipe_size);
   531    ASSERT_THAT(write(wfd.get(), buf.data(), buf.size()),
   532                SyscallSucceedsWithValue(pipe_size));
   533  
   534    EXPECT_THAT(sendfile(wfd.get(), inf.get(), nullptr, kDataSize),
   535                SyscallFailsWithErrno(EWOULDBLOCK));
   536  }
   537  
   538  TEST(SendFileTest, SendPipeEOF) {
   539    // Create and open an empty input file.
   540    const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
   541    const FileDescriptor inf =
   542        ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY));
   543  
   544    // Setup the output named pipe.
   545    int fds[2];
   546    ASSERT_THAT(pipe2(fds, O_NONBLOCK), SyscallSucceeds());
   547    const FileDescriptor rfd(fds[0]);
   548    const FileDescriptor wfd(fds[1]);
   549  
   550    EXPECT_THAT(sendfile(wfd.get(), inf.get(), nullptr, 123),
   551                SyscallSucceedsWithValue(0));
   552  }
   553  
   554  TEST(SendFileTest, SendToFullPipeReturnsEAGAIN) {
   555    // Create and open an empty input file.
   556    const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
   557    const FileDescriptor in_fd =
   558        ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDWR));
   559  
   560    // Set up the output pipe.
   561    int fds[2];
   562    ASSERT_THAT(pipe2(fds, O_NONBLOCK), SyscallSucceeds());
   563    const FileDescriptor rfd(fds[0]);
   564    const FileDescriptor wfd(fds[1]);
   565  
   566    int pipe_size = -1;
   567    ASSERT_THAT(pipe_size = fcntl(wfd.get(), F_GETPIPE_SZ), SyscallSucceeds());
   568    int data_size = pipe_size * 8;
   569    ASSERT_THAT(ftruncate(in_fd.get(), data_size), SyscallSucceeds());
   570  
   571    ASSERT_THAT(sendfile(wfd.get(), in_fd.get(), 0, data_size),
   572                SyscallSucceeds());
   573    EXPECT_THAT(sendfile(wfd.get(), in_fd.get(), 0, data_size),
   574                SyscallFailsWithErrno(EAGAIN));
   575  }
   576  
   577  TEST(SendFileTest, SendPipeBlocks) {
   578    // Create temp file.
   579    constexpr char kData[] =
   580        "The fault, dear Brutus, is not in our stars, but in ourselves.";
   581    constexpr int kDataSize = sizeof(kData) - 1;
   582    const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith(
   583        GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode));
   584  
   585    // Open the input file as read only.
   586    const FileDescriptor inf =
   587        ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY));
   588  
   589    // Setup the output named pipe.
   590    int fds[2];
   591    ASSERT_THAT(pipe(fds), SyscallSucceeds());
   592    const FileDescriptor rfd(fds[0]);
   593    const FileDescriptor wfd(fds[1]);
   594  
   595    // Fill up the pipe's buffer.
   596    int pipe_size = -1;
   597    ASSERT_THAT(pipe_size = fcntl(wfd.get(), F_GETPIPE_SZ), SyscallSucceeds());
   598    std::vector<char> buf(pipe_size);
   599    ASSERT_THAT(write(wfd.get(), buf.data(), buf.size()),
   600                SyscallSucceedsWithValue(pipe_size));
   601  
   602    ScopedThread t([&]() {
   603      absl::SleepFor(absl::Milliseconds(100));
   604      ASSERT_THAT(read(rfd.get(), buf.data(), buf.size()),
   605                  SyscallSucceedsWithValue(pipe_size));
   606    });
   607  
   608    EXPECT_THAT(sendfile(wfd.get(), inf.get(), nullptr, kDataSize),
   609                SyscallSucceedsWithValue(kDataSize));
   610  }
   611  
   612  TEST(SendFileTest, SendToSpecialFile) {
   613    // Create temp file.
   614    const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith(
   615        GetAbsoluteTestTmpdir(), "", TempPath::kDefaultFileMode));
   616  
   617    const FileDescriptor inf =
   618        ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDWR));
   619    constexpr int kSize = 0x7ff;
   620    ASSERT_THAT(ftruncate(inf.get(), kSize), SyscallSucceeds());
   621  
   622    auto eventfd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD());
   623  
   624    // eventfd can accept a number of bytes which is a multiple of 8.
   625    EXPECT_THAT(sendfile(eventfd.get(), inf.get(), nullptr, 0xfffff),
   626                SyscallSucceedsWithValue(kSize & (~7)));
   627  }
   628  
   629  TEST(SendFileTest, SendFileToPipe) {
   630    // Create temp file.
   631    constexpr char kData[] = "<insert-quote-here>";
   632    constexpr int kDataSize = sizeof(kData) - 1;
   633    const TempPath in_file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith(
   634        GetAbsoluteTestTmpdir(), kData, TempPath::kDefaultFileMode));
   635    const FileDescriptor inf =
   636        ASSERT_NO_ERRNO_AND_VALUE(Open(in_file.path(), O_RDONLY));
   637  
   638    // Create a pipe for sending to a pipe.
   639    int fds[2];
   640    ASSERT_THAT(pipe(fds), SyscallSucceeds());
   641    const FileDescriptor rfd(fds[0]);
   642    const FileDescriptor wfd(fds[1]);
   643  
   644    // Expect to read up to the given size.
   645    std::vector<char> buf(kDataSize);
   646    ScopedThread t([&]() {
   647      absl::SleepFor(absl::Milliseconds(100));
   648      ASSERT_THAT(read(rfd.get(), buf.data(), buf.size()),
   649                  SyscallSucceedsWithValue(kDataSize));
   650    });
   651  
   652    // Send with twice the size of the file, which should hit EOF.
   653    EXPECT_THAT(sendfile(wfd.get(), inf.get(), nullptr, kDataSize * 2),
   654                SyscallSucceedsWithValue(kDataSize));
   655  }
   656  
   657  TEST(SendFileTest, SendFileToSelf) {
   658    int rawfd;
   659    ASSERT_THAT(rawfd = memfd_create("memfd", 0), SyscallSucceeds());
   660    const FileDescriptor fd(rawfd);
   661  
   662    char c = 0x01;
   663    ASSERT_THAT(WriteFd(fd.get(), &c, 1), SyscallSucceedsWithValue(1));
   664  
   665    // Arbitrarily chosen to make sendfile() take long enough that the sentry
   666    // watchdog usually fires unless it's reset by sendfile() between iterations
   667    // of the buffered copy. See b/172076632.
   668    constexpr size_t kSendfileSize = 0xa00000;
   669  
   670    off_t offset = 0;
   671    ASSERT_THAT(sendfile(fd.get(), fd.get(), &offset, kSendfileSize),
   672                SyscallSucceedsWithValue(kSendfileSize));
   673  }
   674  
   675  static volatile int signaled = 0;
   676  void SigUsr1Handler(int sig, siginfo_t* info, void* context) { signaled = 1; }
   677  
   678  TEST(SendFileTest, ToEventFDDoesNotSpin) {
   679    FileDescriptor efd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, 0));
   680  
   681    // Write the maximum value of an eventfd to a file.
   682    const uint64_t kMaxEventfdValue = 0xfffffffffffffffe;
   683    const auto tempfile = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFile());
   684    const auto tempfd = ASSERT_NO_ERRNO_AND_VALUE(Open(tempfile.path(), O_RDWR));
   685    ASSERT_THAT(
   686        pwrite(tempfd.get(), &kMaxEventfdValue, sizeof(kMaxEventfdValue), 0),
   687        SyscallSucceedsWithValue(sizeof(kMaxEventfdValue)));
   688  
   689    // Set the eventfd's value to 1.
   690    const uint64_t kOne = 1;
   691    ASSERT_THAT(write(efd.get(), &kOne, sizeof(kOne)),
   692                SyscallSucceedsWithValue(sizeof(kOne)));
   693  
   694    // Set up signal handler.
   695    struct sigaction sa = {};
   696    sa.sa_sigaction = SigUsr1Handler;
   697    sa.sa_flags = SA_SIGINFO;
   698    const auto cleanup_sigact =
   699        ASSERT_NO_ERRNO_AND_VALUE(ScopedSigaction(SIGUSR1, sa));
   700  
   701    // Send SIGUSR1 to this thread in 1 second.
   702    struct sigevent sev = {};
   703    sev.sigev_notify = SIGEV_THREAD_ID;
   704    sev.sigev_signo = SIGUSR1;
   705    sev.sigev_notify_thread_id = gettid();
   706    auto timer = ASSERT_NO_ERRNO_AND_VALUE(TimerCreate(CLOCK_MONOTONIC, sev));
   707    struct itimerspec its = {};
   708    its.it_value = absl::ToTimespec(absl::Seconds(1));
   709    DisableSave ds;  // Asserting an EINTR.
   710    ASSERT_NO_ERRNO(timer.Set(0, its));
   711  
   712    // Sendfile from tempfd to the eventfd. Since the eventfd is not already at
   713    // its maximum value, the eventfd is "ready for writing"; however, since the
   714    // eventfd's existing value plus the new value would exceed the maximum, the
   715    // write should internally fail with EWOULDBLOCK. In this case, sendfile()
   716    // should block instead of spinning, and eventually be interrupted by our
   717    // timer. See b/172075629.
   718    EXPECT_THAT(
   719        sendfile(efd.get(), tempfd.get(), nullptr, sizeof(kMaxEventfdValue)),
   720        SyscallFailsWithErrno(EINTR));
   721  
   722    // Signal should have been handled.
   723    EXPECT_EQ(signaled, 1);
   724  }
   725  
   726  }  // namespace
   727  
   728  }  // namespace testing
   729  }  // namespace gvisor