github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/images/basic/integrationtest/link_test.c (about)

     1  // Copyright 2020 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 <err.h>
    16  #include <fcntl.h>
    17  #include <string.h>
    18  #include <sys/stat.h>
    19  #include <sys/types.h>
    20  #include <unistd.h>
    21  
    22  // Basic test for linkat(2). Syscall tests requires CAP_DAC_READ_SEARCH and it
    23  // cannot use tricks like userns as root. For this reason, run a basic link test
    24  // to ensure some coverage.
    25  int main(int argc, char** argv) {
    26    const char kOldPath[] = "old.txt";
    27    int fd = open(kOldPath, O_RDWR | O_CREAT | O_TRUNC, 0600);
    28    if (fd < 0) {
    29      errx(1, "open(%s) failed", kOldPath);
    30    }
    31    const char kData[] = "some random content";
    32    if (write(fd, kData, sizeof(kData)) < 0) {
    33      err(1, "write failed");
    34    }
    35    close(fd);
    36  
    37    struct stat old_stat;
    38    if (stat(kOldPath, &old_stat)) {
    39      errx(1, "stat(%s) failed", kOldPath);
    40    }
    41  
    42    const char kNewPath[] = "new.txt";
    43    if (link(kOldPath, kNewPath)) {
    44      errx(1, "link(%s, %s) failed", kOldPath, kNewPath);
    45    }
    46  
    47    struct stat new_stat;
    48    if (stat(kNewPath, &new_stat)) {
    49      errx(1, "stat(%s) failed", kNewPath);
    50    }
    51  
    52    // Check that files are the same.
    53    if (old_stat.st_dev != new_stat.st_dev) {
    54      errx(1, "files st_dev is different, want: %lu, got: %lu", old_stat.st_dev,
    55           new_stat.st_dev);
    56    }
    57    if (old_stat.st_ino != new_stat.st_ino) {
    58      errx(1, "files st_ino is different, want: %lu, got: %lu", old_stat.st_ino,
    59           new_stat.st_ino);
    60    }
    61  
    62    // Check that link count is correct.
    63    if (new_stat.st_nlink != old_stat.st_nlink + 1) {
    64      errx(1, "wrong nlink, want: %lu, got: %lu", old_stat.st_nlink + 1,
    65           new_stat.st_nlink);
    66    }
    67  
    68    // Check taht contents are the same.
    69    fd = open(kNewPath, O_RDONLY);
    70    if (fd < 0) {
    71      errx(1, "open(%s) failed", kNewPath);
    72    }
    73    char buf[sizeof(kData)] = {};
    74    if (read(fd, buf, sizeof(buf)) < 0) {
    75      err(1, "read failed");
    76    }
    77    close(fd);
    78  
    79    if (strcmp(buf, kData) != 0) {
    80      errx(1, "file content mismatch: %s", buf);
    81    }
    82  
    83    // Cleanup.
    84    if (unlink(kNewPath)) {
    85      errx(1, "unlink(%s) failed", kNewPath);
    86    }
    87    if (unlink(kOldPath)) {
    88      errx(1, "unlink(%s) failed", kOldPath);
    89    }
    90  
    91    // Success!
    92    return 0;
    93  }