11801c356SMichael Jones //===-- Unittests for syscalls --------------------------------------------===// 21801c356SMichael Jones // 31801c356SMichael Jones // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41801c356SMichael Jones // See https://llvm.org/LICENSE.txt for license information. 51801c356SMichael Jones // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61801c356SMichael Jones // 71801c356SMichael Jones //===----------------------------------------------------------------------===// 81801c356SMichael Jones 967de5381SSiva Chandra Reddy #include "src/errno/libc_errno.h" 101801c356SMichael Jones #include "src/unistd/syscall.h" 114f1fe19dSSiva Chandra Reddy #include "test/UnitTest/ErrnoSetterMatcher.h" 12af1315c2SSiva Chandra Reddy #include "test/UnitTest/Test.h" 131801c356SMichael Jones 14*abc49cc1SJob Henandez Lara #include "hdr/fcntl_macros.h" 15c0ad6e2fSNick Desaulniers #include <sys/stat.h> // For S_* flags. 161801c356SMichael Jones #include <sys/syscall.h> // For syscall numbers. 171801c356SMichael Jones #include <unistd.h> 181801c356SMichael Jones 19b6bc9d72SGuillaume Chatelet using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; 201801c356SMichael Jones 211801c356SMichael Jones // We only do a smoke test here. Actual functionality tests are 221801c356SMichael Jones // done by the unit tests of the syscall wrappers like mmap. 231801c356SMichael Jones // The goal is to test syscalls with a wide number of args. 241801c356SMichael Jones 251801c356SMichael Jones // There is no function named "syscall" in llvm-libc, we instead use a macro to 261801c356SMichael Jones // set up the arguments properly. We still need to specify the namespace though 271801c356SMichael Jones // because the macro generates a call to the actual internal function 28d4041301Salfredfo // (__llvm_libc_syscall) which is inside the namespace. 291801c356SMichael Jones TEST(LlvmLibcSyscallTest, TrivialCall) { 303eb1e6d8Smichaelrj-google LIBC_NAMESPACE::libc_errno = 0; 311801c356SMichael Jones 32b6bc9d72SGuillaume Chatelet ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_gettid), 0l); 3373874f7aSGuillaume Chatelet ASSERT_ERRNO_SUCCESS(); 341801c356SMichael Jones } 351801c356SMichael Jones 361801c356SMichael Jones TEST(LlvmLibcSyscallTest, SymlinkCreateDestroy) { 371801c356SMichael Jones constexpr const char LINK_VAL[] = "syscall_readlink_test_value"; 381801c356SMichael Jones constexpr const char LINK[] = "testdata/syscall_readlink.test.link"; 391801c356SMichael Jones 401990ce74SMikhail R. Gadelha #ifdef SYS_symlink 41b6bc9d72SGuillaume Chatelet ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_symlink, LINK_VAL, LINK), 0l); 421990ce74SMikhail R. Gadelha #elif defined(SYS_symlinkat) 43b6bc9d72SGuillaume Chatelet ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_symlinkat, LINK_VAL, AT_FDCWD, LINK), 44b6bc9d72SGuillaume Chatelet 0l); 451990ce74SMikhail R. Gadelha #else 465b22df99SMikhail R. Gadelha #error "symlink and symlinkat syscalls not available." 471990ce74SMikhail R. Gadelha #endif 4873874f7aSGuillaume Chatelet ASSERT_ERRNO_SUCCESS(); 491801c356SMichael Jones 501801c356SMichael Jones char buf[sizeof(LINK_VAL)]; 511801c356SMichael Jones 521990ce74SMikhail R. Gadelha #ifdef SYS_readlink 53b6bc9d72SGuillaume Chatelet ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_readlink, LINK, buf, sizeof(buf)), 0l); 541990ce74SMikhail R. Gadelha #elif defined(SYS_readlinkat) 551990ce74SMikhail R. Gadelha ASSERT_GE( 56b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::syscall(SYS_readlinkat, AT_FDCWD, LINK, buf, sizeof(buf)), 571990ce74SMikhail R. Gadelha 0l); 581990ce74SMikhail R. Gadelha #endif 5973874f7aSGuillaume Chatelet ASSERT_ERRNO_SUCCESS(); 601801c356SMichael Jones 611990ce74SMikhail R. Gadelha #ifdef SYS_unlink 62b6bc9d72SGuillaume Chatelet ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlink, LINK), 0l); 631990ce74SMikhail R. Gadelha #elif defined(SYS_unlinkat) 64b6bc9d72SGuillaume Chatelet ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlinkat, AT_FDCWD, LINK, 0), 0l); 651990ce74SMikhail R. Gadelha #else 665b22df99SMikhail R. Gadelha #error "unlink and unlinkat syscalls not available." 671990ce74SMikhail R. Gadelha #endif 6873874f7aSGuillaume Chatelet ASSERT_ERRNO_SUCCESS(); 691801c356SMichael Jones } 701801c356SMichael Jones 711801c356SMichael Jones TEST(LlvmLibcSyscallTest, FileReadWrite) { 721801c356SMichael Jones constexpr const char HELLO[] = "hello"; 731801c356SMichael Jones constexpr int HELLO_SIZE = sizeof(HELLO); 741801c356SMichael Jones 751801c356SMichael Jones constexpr const char *TEST_FILE = "testdata/syscall_pread_pwrite.test"; 761801c356SMichael Jones 771990ce74SMikhail R. Gadelha #ifdef SYS_open 781801c356SMichael Jones int fd = 79b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::syscall(SYS_open, TEST_FILE, O_WRONLY | O_CREAT, S_IRWXU); 801990ce74SMikhail R. Gadelha #elif defined(SYS_openat) 81b6bc9d72SGuillaume Chatelet int fd = LIBC_NAMESPACE::syscall(SYS_openat, AT_FDCWD, TEST_FILE, 821990ce74SMikhail R. Gadelha O_WRONLY | O_CREAT, S_IRWXU); 831990ce74SMikhail R. Gadelha #else 845b22df99SMikhail R. Gadelha #error "open and openat syscalls not available." 851990ce74SMikhail R. Gadelha #endif 861801c356SMichael Jones ASSERT_GT(fd, 0); 8773874f7aSGuillaume Chatelet ASSERT_ERRNO_SUCCESS(); 881801c356SMichael Jones 89b6bc9d72SGuillaume Chatelet ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_pwrite64, fd, HELLO, HELLO_SIZE, 0), 90b6bc9d72SGuillaume Chatelet 0l); 9173874f7aSGuillaume Chatelet ASSERT_ERRNO_SUCCESS(); 921801c356SMichael Jones 93b6bc9d72SGuillaume Chatelet ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_fsync, fd), 0l); 9473874f7aSGuillaume Chatelet ASSERT_ERRNO_SUCCESS(); 951801c356SMichael Jones 96b6bc9d72SGuillaume Chatelet ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_close, fd), 0l); 9773874f7aSGuillaume Chatelet ASSERT_ERRNO_SUCCESS(); 981801c356SMichael Jones } 991801c356SMichael Jones 1001801c356SMichael Jones TEST(LlvmLibcSyscallTest, FileLinkCreateDestroy) { 1011801c356SMichael Jones constexpr const char *TEST_DIR = "testdata"; 1021801c356SMichael Jones constexpr const char *TEST_FILE = "syscall_linkat.test"; 1031801c356SMichael Jones constexpr const char *TEST_FILE_PATH = "testdata/syscall_linkat.test"; 1041801c356SMichael Jones constexpr const char *TEST_FILE_LINK = "syscall_linkat.test.link"; 1051801c356SMichael Jones constexpr const char *TEST_FILE_LINK_PATH = 1061801c356SMichael Jones "testdata/syscall_linkat.test.link"; 1071801c356SMichael Jones 1081801c356SMichael Jones // The test strategy is as follows: 1091801c356SMichael Jones // 1. Create a normal file 1101801c356SMichael Jones // 2. Create a link to that file. 1111801c356SMichael Jones // 3. Open the link to check that the link was created. 1121801c356SMichael Jones // 4. Cleanup the file and its link. 1131801c356SMichael Jones 1141990ce74SMikhail R. Gadelha #ifdef SYS_open 115b6bc9d72SGuillaume Chatelet int write_fd = LIBC_NAMESPACE::syscall(SYS_open, TEST_FILE_PATH, 1161801c356SMichael Jones O_WRONLY | O_CREAT, S_IRWXU); 1171990ce74SMikhail R. Gadelha #elif defined(SYS_openat) 118b6bc9d72SGuillaume Chatelet int write_fd = LIBC_NAMESPACE::syscall(SYS_openat, AT_FDCWD, TEST_FILE_PATH, 1191990ce74SMikhail R. Gadelha O_WRONLY | O_CREAT, S_IRWXU); 1201990ce74SMikhail R. Gadelha #else 1215b22df99SMikhail R. Gadelha #error "open and openat syscalls not available." 1221990ce74SMikhail R. Gadelha #endif 1231801c356SMichael Jones ASSERT_GT(write_fd, 0); 12473874f7aSGuillaume Chatelet ASSERT_ERRNO_SUCCESS(); 1251801c356SMichael Jones 126b6bc9d72SGuillaume Chatelet ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_close, write_fd), 0l); 12773874f7aSGuillaume Chatelet ASSERT_ERRNO_SUCCESS(); 1281801c356SMichael Jones 1291990ce74SMikhail R. Gadelha #ifdef SYS_open 130b6bc9d72SGuillaume Chatelet int dir_fd = LIBC_NAMESPACE::syscall(SYS_open, TEST_DIR, O_DIRECTORY, 0); 1311990ce74SMikhail R. Gadelha #elif defined(SYS_openat) 1321990ce74SMikhail R. Gadelha int dir_fd = 133b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::syscall(SYS_openat, AT_FDCWD, TEST_DIR, O_DIRECTORY, 0); 1341990ce74SMikhail R. Gadelha #else 1355b22df99SMikhail R. Gadelha #error "open and openat syscalls not available." 1361990ce74SMikhail R. Gadelha #endif 1371801c356SMichael Jones ASSERT_GT(dir_fd, 0); 13873874f7aSGuillaume Chatelet ASSERT_ERRNO_SUCCESS(); 1391801c356SMichael Jones 140b6bc9d72SGuillaume Chatelet ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_linkat, dir_fd, TEST_FILE, dir_fd, 1411801c356SMichael Jones TEST_FILE_LINK, 0), 1421801c356SMichael Jones 0l); 14373874f7aSGuillaume Chatelet ASSERT_ERRNO_SUCCESS(); 1441990ce74SMikhail R. Gadelha #ifdef SYS_open 145b6bc9d72SGuillaume Chatelet int link_fd = 146b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::syscall(SYS_open, TEST_FILE_LINK_PATH, O_PATH, 0); 1471990ce74SMikhail R. Gadelha #elif defined(SYS_openat) 148b6bc9d72SGuillaume Chatelet int link_fd = LIBC_NAMESPACE::syscall(SYS_openat, AT_FDCWD, 149b6bc9d72SGuillaume Chatelet TEST_FILE_LINK_PATH, O_PATH, 0); 1501990ce74SMikhail R. Gadelha #else 1515b22df99SMikhail R. Gadelha #error "open and openat syscalls not available." 1521990ce74SMikhail R. Gadelha #endif 1531801c356SMichael Jones ASSERT_GT(link_fd, 0); 15473874f7aSGuillaume Chatelet ASSERT_ERRNO_SUCCESS(); 1551801c356SMichael Jones 1561990ce74SMikhail R. Gadelha #ifdef SYS_unlink 157b6bc9d72SGuillaume Chatelet ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlink, TEST_FILE_PATH), 0l); 1581990ce74SMikhail R. Gadelha #elif defined(SYS_unlinkat) 159b6bc9d72SGuillaume Chatelet ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlinkat, AT_FDCWD, TEST_FILE_PATH, 0), 1601990ce74SMikhail R. Gadelha 0l); 1611990ce74SMikhail R. Gadelha #else 1625b22df99SMikhail R. Gadelha #error "unlink and unlinkat syscalls not available." 1631990ce74SMikhail R. Gadelha #endif 16473874f7aSGuillaume Chatelet ASSERT_ERRNO_SUCCESS(); 1651801c356SMichael Jones 1661990ce74SMikhail R. Gadelha #ifdef SYS_unlink 167b6bc9d72SGuillaume Chatelet ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_unlink, TEST_FILE_LINK_PATH), 0l); 1681990ce74SMikhail R. Gadelha #elif defined(SYS_unlinkat) 1691990ce74SMikhail R. Gadelha ASSERT_GE( 170b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::syscall(SYS_unlinkat, AT_FDCWD, TEST_FILE_LINK_PATH, 0), 171b6bc9d72SGuillaume Chatelet 0l); 1721990ce74SMikhail R. Gadelha #else 1735b22df99SMikhail R. Gadelha #error "unlink and unlinkat syscalls not available." 1741990ce74SMikhail R. Gadelha #endif 17573874f7aSGuillaume Chatelet ASSERT_ERRNO_SUCCESS(); 1761801c356SMichael Jones 177b6bc9d72SGuillaume Chatelet ASSERT_GE(LIBC_NAMESPACE::syscall(SYS_close, dir_fd), 0l); 17873874f7aSGuillaume Chatelet ASSERT_ERRNO_SUCCESS(); 1791801c356SMichael Jones } 180