1668a58b8STom Eccles //===-- flang/unittests/Runtime/AccessTest.cpp ----------------------------===// 2668a58b8STom Eccles // 3668a58b8STom Eccles // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4668a58b8STom Eccles // See https://llvm.org/LICENSE.txt for license information. 5668a58b8STom Eccles // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6668a58b8STom Eccles // 7668a58b8STom Eccles //===----------------------------------------------------------------------===// 8668a58b8STom Eccles 9668a58b8STom Eccles // TODO: ACCESS is not yet implemented on Windows 10668a58b8STom Eccles #ifndef _WIN32 11668a58b8STom Eccles 12668a58b8STom Eccles #include "CrashHandlerFixture.h" 13668a58b8STom Eccles #include "gtest/gtest.h" 14668a58b8STom Eccles #include "flang/Runtime/extensions.h" 15668a58b8STom Eccles #include "llvm/ADT/Twine.h" 16668a58b8STom Eccles 17668a58b8STom Eccles #include <fcntl.h> 18668a58b8STom Eccles #include <sys/stat.h> 19668a58b8STom Eccles #include <sys/types.h> 20668a58b8STom Eccles #include <unistd.h> 21668a58b8STom Eccles 22668a58b8STom Eccles namespace { 23668a58b8STom Eccles 24668a58b8STom Eccles struct AccessTests : public CrashHandlerFixture {}; 25668a58b8STom Eccles 26668a58b8STom Eccles struct AccessType { 27668a58b8STom Eccles bool read{false}; 28668a58b8STom Eccles bool write{false}; 29668a58b8STom Eccles bool execute{false}; 30668a58b8STom Eccles bool exists{false}; 31668a58b8STom Eccles }; 32668a58b8STom Eccles 33668a58b8STom Eccles } // namespace 34668a58b8STom Eccles 35*32403f79STom Eccles static bool userSkipsPermissionChecks() { 36*32403f79STom Eccles // The tests in this file assume normal permission checks apply to the user 37*32403f79STom Eccles // running the tests. This isn't true when the test is run by root. 38*32403f79STom Eccles return geteuid() == 0; 39*32403f79STom Eccles } 40*32403f79STom Eccles 41668a58b8STom Eccles static std::string addPIDSuffix(const char *name) { 42668a58b8STom Eccles std::stringstream ss; 43668a58b8STom Eccles ss << name; 44668a58b8STom Eccles ss << '.'; 45668a58b8STom Eccles 46668a58b8STom Eccles ss << getpid(); 47668a58b8STom Eccles 48668a58b8STom Eccles return ss.str(); 49668a58b8STom Eccles } 50668a58b8STom Eccles 51668a58b8STom Eccles static bool exists(const std::string &path) { 52668a58b8STom Eccles return access(path.c_str(), F_OK) == 0; 53668a58b8STom Eccles } 54668a58b8STom Eccles 55668a58b8STom Eccles // Implementation of std::filesystem::temp_directory_path adapted from libcxx 56668a58b8STom Eccles // See llvm-project/libcxx/src/filesystem/operations.cpp 57668a58b8STom Eccles // Using std::filesystem is inconvenient because the required flags are not 58668a58b8STom Eccles // consistent accross compilers and CMake doesn't have built in support to 59668a58b8STom Eccles // determine the correct flags. 60668a58b8STom Eccles static const char *temp_directory_path() { 61668a58b8STom Eccles // TODO: Windows 62668a58b8STom Eccles const char *env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"}; 63668a58b8STom Eccles const char *ret = nullptr; 64668a58b8STom Eccles 65668a58b8STom Eccles for (auto &ep : env_paths) { 66668a58b8STom Eccles if ((ret = getenv(ep))) { 67668a58b8STom Eccles break; 68668a58b8STom Eccles } 69668a58b8STom Eccles } 70668a58b8STom Eccles 71668a58b8STom Eccles if (ret == nullptr) { 72668a58b8STom Eccles #if defined(__ANDROID__) 73668a58b8STom Eccles ret = "/data/local/tmp"; 74668a58b8STom Eccles #else 75668a58b8STom Eccles ret = "/tmp"; 76668a58b8STom Eccles #endif 77668a58b8STom Eccles } 78668a58b8STom Eccles 79668a58b8STom Eccles assert(exists(ret)); 80668a58b8STom Eccles return ret; 81668a58b8STom Eccles } 82668a58b8STom Eccles 83668a58b8STom Eccles static std::string createTemporaryFile( 84668a58b8STom Eccles const char *name, const AccessType &accessType) { 85668a58b8STom Eccles std::string path = 86668a58b8STom Eccles (llvm::Twine{temp_directory_path()} + "/" + addPIDSuffix(name)).str(); 87668a58b8STom Eccles 88668a58b8STom Eccles // O_CREAT | O_EXCL enforces that this file is newly created by this call. 89668a58b8STom Eccles // This feels risky. If we don't have permission to create files in the 90668a58b8STom Eccles // temporary directory or if the files already exist, the test will fail. 91668a58b8STom Eccles // But we can't use std::tmpfile() because we need a path to the file and 92668a58b8STom Eccles // to control the filesystem permissions 93668a58b8STom Eccles mode_t mode{0}; 94668a58b8STom Eccles if (accessType.read) { 95668a58b8STom Eccles mode |= S_IRUSR; 96668a58b8STom Eccles } 97668a58b8STom Eccles if (accessType.write) { 98668a58b8STom Eccles mode |= S_IWUSR; 99668a58b8STom Eccles } 100668a58b8STom Eccles if (accessType.execute) { 101668a58b8STom Eccles mode |= S_IXUSR; 102668a58b8STom Eccles } 103668a58b8STom Eccles 104668a58b8STom Eccles int file = open(path.c_str(), O_CREAT | O_EXCL, mode); 105668a58b8STom Eccles if (file == -1) { 106668a58b8STom Eccles return {}; 107668a58b8STom Eccles } 108668a58b8STom Eccles 109668a58b8STom Eccles close(file); 110668a58b8STom Eccles 111668a58b8STom Eccles return path; 112668a58b8STom Eccles } 113668a58b8STom Eccles 114668a58b8STom Eccles static std::int64_t callAccess( 115668a58b8STom Eccles const std::string &path, const AccessType &accessType) { 116668a58b8STom Eccles const char *cpath{path.c_str()}; 117668a58b8STom Eccles std::int64_t pathlen = std::strlen(cpath); 118668a58b8STom Eccles 119668a58b8STom Eccles std::string mode; 120668a58b8STom Eccles if (accessType.read) { 121668a58b8STom Eccles mode += 'r'; 122668a58b8STom Eccles } 123668a58b8STom Eccles if (accessType.write) { 124668a58b8STom Eccles mode += 'w'; 125668a58b8STom Eccles } 126668a58b8STom Eccles if (accessType.execute) { 127668a58b8STom Eccles mode += 'x'; 128668a58b8STom Eccles } 129668a58b8STom Eccles if (accessType.exists) { 130668a58b8STom Eccles mode += ' '; 131668a58b8STom Eccles } 132668a58b8STom Eccles 133668a58b8STom Eccles const char *cmode = mode.c_str(); 134668a58b8STom Eccles std::int64_t modelen = std::strlen(cmode); 135668a58b8STom Eccles 136668a58b8STom Eccles return FORTRAN_PROCEDURE_NAME(access)(cpath, pathlen, cmode, modelen); 137668a58b8STom Eccles } 138668a58b8STom Eccles 139668a58b8STom Eccles TEST(AccessTests, TestExists) { 140668a58b8STom Eccles AccessType accessType; 141668a58b8STom Eccles accessType.exists = true; 142668a58b8STom Eccles 143668a58b8STom Eccles std::string path = createTemporaryFile(__func__, accessType); 144668a58b8STom Eccles ASSERT_FALSE(path.empty()); 145668a58b8STom Eccles 146668a58b8STom Eccles std::int64_t res = callAccess(path, accessType); 147668a58b8STom Eccles 148668a58b8STom Eccles ASSERT_EQ(unlink(path.c_str()), 0); 149668a58b8STom Eccles 150668a58b8STom Eccles ASSERT_EQ(res, 0); 151668a58b8STom Eccles } 152668a58b8STom Eccles 153668a58b8STom Eccles TEST(AccessTests, TestNotExists) { 154668a58b8STom Eccles std::string nonExistant{addPIDSuffix(__func__)}; 155668a58b8STom Eccles ASSERT_FALSE(exists(nonExistant)); 156668a58b8STom Eccles 157668a58b8STom Eccles AccessType accessType; 158668a58b8STom Eccles accessType.exists = true; 159668a58b8STom Eccles std::int64_t res = callAccess(nonExistant, accessType); 160668a58b8STom Eccles 161668a58b8STom Eccles ASSERT_NE(res, 0); 162668a58b8STom Eccles } 163668a58b8STom Eccles 164668a58b8STom Eccles TEST(AccessTests, TestRead) { 165668a58b8STom Eccles AccessType accessType; 166668a58b8STom Eccles accessType.read = true; 167668a58b8STom Eccles 168668a58b8STom Eccles std::string path = createTemporaryFile(__func__, accessType); 169668a58b8STom Eccles ASSERT_FALSE(path.empty()); 170668a58b8STom Eccles 171668a58b8STom Eccles std::int64_t res = callAccess(path, accessType); 172668a58b8STom Eccles 173668a58b8STom Eccles ASSERT_EQ(unlink(path.c_str()), 0); 174668a58b8STom Eccles 175*32403f79STom Eccles if (userSkipsPermissionChecks()) { 176*32403f79STom Eccles return; 177*32403f79STom Eccles } 178*32403f79STom Eccles 179668a58b8STom Eccles ASSERT_EQ(res, 0); 180668a58b8STom Eccles } 181668a58b8STom Eccles 182668a58b8STom Eccles TEST(AccessTests, TestNotRead) { 183668a58b8STom Eccles AccessType accessType; 184668a58b8STom Eccles accessType.read = false; 185668a58b8STom Eccles 186668a58b8STom Eccles std::string path = createTemporaryFile(__func__, accessType); 187668a58b8STom Eccles ASSERT_FALSE(path.empty()); 188668a58b8STom Eccles 189668a58b8STom Eccles accessType.read = true; 190668a58b8STom Eccles std::int64_t res = callAccess(path, accessType); 191668a58b8STom Eccles 192668a58b8STom Eccles ASSERT_EQ(unlink(path.c_str()), 0); 193668a58b8STom Eccles 194*32403f79STom Eccles if (userSkipsPermissionChecks()) { 195*32403f79STom Eccles return; 196*32403f79STom Eccles } 197*32403f79STom Eccles 198668a58b8STom Eccles ASSERT_NE(res, 0); 199668a58b8STom Eccles } 200668a58b8STom Eccles 201668a58b8STom Eccles TEST(AccessTests, TestWrite) { 202668a58b8STom Eccles AccessType accessType; 203668a58b8STom Eccles accessType.write = true; 204668a58b8STom Eccles 205668a58b8STom Eccles std::string path = createTemporaryFile(__func__, accessType); 206668a58b8STom Eccles ASSERT_FALSE(path.empty()); 207668a58b8STom Eccles 208668a58b8STom Eccles std::int64_t res = callAccess(path, accessType); 209668a58b8STom Eccles 210668a58b8STom Eccles ASSERT_EQ(unlink(path.c_str()), 0); 211668a58b8STom Eccles 212*32403f79STom Eccles if (userSkipsPermissionChecks()) { 213*32403f79STom Eccles return; 214*32403f79STom Eccles } 215*32403f79STom Eccles 216668a58b8STom Eccles ASSERT_EQ(res, 0); 217668a58b8STom Eccles } 218668a58b8STom Eccles 219668a58b8STom Eccles TEST(AccessTests, TestNotWrite) { 220668a58b8STom Eccles AccessType accessType; 221668a58b8STom Eccles accessType.write = false; 222668a58b8STom Eccles 223668a58b8STom Eccles std::string path = createTemporaryFile(__func__, accessType); 224668a58b8STom Eccles ASSERT_FALSE(path.empty()); 225668a58b8STom Eccles 226668a58b8STom Eccles accessType.write = true; 227668a58b8STom Eccles std::int64_t res = callAccess(path, accessType); 228668a58b8STom Eccles 229668a58b8STom Eccles ASSERT_EQ(unlink(path.c_str()), 0); 230668a58b8STom Eccles 231*32403f79STom Eccles if (userSkipsPermissionChecks()) { 232*32403f79STom Eccles return; 233*32403f79STom Eccles } 234*32403f79STom Eccles 235668a58b8STom Eccles ASSERT_NE(res, 0); 236668a58b8STom Eccles } 237668a58b8STom Eccles 238668a58b8STom Eccles TEST(AccessTests, TestReadWrite) { 239668a58b8STom Eccles AccessType accessType; 240668a58b8STom Eccles accessType.read = true; 241668a58b8STom Eccles accessType.write = true; 242668a58b8STom Eccles 243668a58b8STom Eccles std::string path = createTemporaryFile(__func__, accessType); 244668a58b8STom Eccles ASSERT_FALSE(path.empty()); 245668a58b8STom Eccles 246668a58b8STom Eccles std::int64_t res = callAccess(path, accessType); 247668a58b8STom Eccles 248668a58b8STom Eccles ASSERT_EQ(unlink(path.c_str()), 0); 249668a58b8STom Eccles 250*32403f79STom Eccles if (userSkipsPermissionChecks()) { 251*32403f79STom Eccles return; 252*32403f79STom Eccles } 253*32403f79STom Eccles 254668a58b8STom Eccles ASSERT_EQ(res, 0); 255668a58b8STom Eccles } 256668a58b8STom Eccles 257668a58b8STom Eccles TEST(AccessTests, TestNotReadWrite0) { 258668a58b8STom Eccles AccessType accessType; 259668a58b8STom Eccles accessType.read = false; 260668a58b8STom Eccles accessType.write = false; 261668a58b8STom Eccles 262668a58b8STom Eccles std::string path = createTemporaryFile(__func__, accessType); 263668a58b8STom Eccles ASSERT_FALSE(path.empty()); 264668a58b8STom Eccles 265668a58b8STom Eccles accessType.read = true; 266668a58b8STom Eccles accessType.write = true; 267668a58b8STom Eccles std::int64_t res = callAccess(path, accessType); 268668a58b8STom Eccles 269668a58b8STom Eccles ASSERT_EQ(unlink(path.c_str()), 0); 270668a58b8STom Eccles 271*32403f79STom Eccles if (userSkipsPermissionChecks()) { 272*32403f79STom Eccles return; 273*32403f79STom Eccles } 274*32403f79STom Eccles 275668a58b8STom Eccles ASSERT_NE(res, 0); 276668a58b8STom Eccles } 277668a58b8STom Eccles 278668a58b8STom Eccles TEST(AccessTests, TestNotReadWrite1) { 279668a58b8STom Eccles AccessType accessType; 280668a58b8STom Eccles accessType.read = true; 281668a58b8STom Eccles accessType.write = false; 282668a58b8STom Eccles 283668a58b8STom Eccles std::string path = createTemporaryFile(__func__, accessType); 284668a58b8STom Eccles ASSERT_FALSE(path.empty()); 285668a58b8STom Eccles 286668a58b8STom Eccles accessType.read = true; 287668a58b8STom Eccles accessType.write = true; 288668a58b8STom Eccles std::int64_t res = callAccess(path, accessType); 289668a58b8STom Eccles 290668a58b8STom Eccles ASSERT_EQ(unlink(path.c_str()), 0); 291668a58b8STom Eccles 292*32403f79STom Eccles if (userSkipsPermissionChecks()) { 293*32403f79STom Eccles return; 294*32403f79STom Eccles } 295*32403f79STom Eccles 296668a58b8STom Eccles ASSERT_NE(res, 0); 297668a58b8STom Eccles } 298668a58b8STom Eccles 299668a58b8STom Eccles TEST(AccessTests, TestNotReadWrite2) { 300668a58b8STom Eccles AccessType accessType; 301668a58b8STom Eccles accessType.read = false; 302668a58b8STom Eccles accessType.write = true; 303668a58b8STom Eccles 304668a58b8STom Eccles std::string path = createTemporaryFile(__func__, accessType); 305668a58b8STom Eccles ASSERT_FALSE(path.empty()); 306668a58b8STom Eccles 307668a58b8STom Eccles accessType.read = true; 308668a58b8STom Eccles accessType.write = true; 309668a58b8STom Eccles std::int64_t res = callAccess(path, accessType); 310668a58b8STom Eccles 311668a58b8STom Eccles ASSERT_EQ(unlink(path.c_str()), 0); 312668a58b8STom Eccles 313*32403f79STom Eccles if (userSkipsPermissionChecks()) { 314*32403f79STom Eccles return; 315*32403f79STom Eccles } 316*32403f79STom Eccles 317668a58b8STom Eccles ASSERT_NE(res, 0); 318668a58b8STom Eccles } 319668a58b8STom Eccles 320668a58b8STom Eccles TEST(AccessTests, TestExecute) { 321668a58b8STom Eccles AccessType accessType; 322668a58b8STom Eccles accessType.execute = true; 323668a58b8STom Eccles 324668a58b8STom Eccles std::string path = createTemporaryFile(__func__, accessType); 325668a58b8STom Eccles ASSERT_FALSE(path.empty()); 326668a58b8STom Eccles 327668a58b8STom Eccles std::int64_t res = callAccess(path, accessType); 328668a58b8STom Eccles 329668a58b8STom Eccles ASSERT_EQ(unlink(path.c_str()), 0); 330668a58b8STom Eccles 331*32403f79STom Eccles if (userSkipsPermissionChecks()) { 332*32403f79STom Eccles return; 333*32403f79STom Eccles } 334*32403f79STom Eccles 335668a58b8STom Eccles ASSERT_EQ(res, 0); 336668a58b8STom Eccles } 337668a58b8STom Eccles 338668a58b8STom Eccles TEST(AccessTests, TestNotExecute) { 339668a58b8STom Eccles AccessType accessType; 340668a58b8STom Eccles accessType.execute = false; 341668a58b8STom Eccles 342668a58b8STom Eccles std::string path = createTemporaryFile(__func__, accessType); 343668a58b8STom Eccles ASSERT_FALSE(path.empty()); 344668a58b8STom Eccles 345668a58b8STom Eccles accessType.execute = true; 346668a58b8STom Eccles std::int64_t res = callAccess(path, accessType); 347668a58b8STom Eccles 348668a58b8STom Eccles ASSERT_EQ(unlink(path.c_str()), 0); 349668a58b8STom Eccles 350*32403f79STom Eccles if (userSkipsPermissionChecks()) { 351*32403f79STom Eccles return; 352*32403f79STom Eccles } 353*32403f79STom Eccles 354668a58b8STom Eccles ASSERT_NE(res, 0); 355668a58b8STom Eccles } 356668a58b8STom Eccles 357668a58b8STom Eccles TEST(AccessTests, TestRWX) { 358668a58b8STom Eccles AccessType accessType; 359668a58b8STom Eccles accessType.read = true; 360668a58b8STom Eccles accessType.write = true; 361668a58b8STom Eccles accessType.execute = true; 362668a58b8STom Eccles 363668a58b8STom Eccles std::string path = createTemporaryFile(__func__, accessType); 364668a58b8STom Eccles ASSERT_FALSE(path.empty()); 365668a58b8STom Eccles 366668a58b8STom Eccles std::int64_t res = callAccess(path, accessType); 367668a58b8STom Eccles 368668a58b8STom Eccles ASSERT_EQ(unlink(path.c_str()), 0); 369668a58b8STom Eccles 370*32403f79STom Eccles if (userSkipsPermissionChecks()) { 371*32403f79STom Eccles return; 372*32403f79STom Eccles } 373*32403f79STom Eccles 374668a58b8STom Eccles ASSERT_EQ(res, 0); 375668a58b8STom Eccles } 376668a58b8STom Eccles 377668a58b8STom Eccles TEST(AccessTests, TestNotRWX0) { 378668a58b8STom Eccles AccessType accessType; 379668a58b8STom Eccles accessType.read = false; 380668a58b8STom Eccles accessType.write = false; 381668a58b8STom Eccles accessType.execute = false; 382668a58b8STom Eccles 383668a58b8STom Eccles std::string path = createTemporaryFile(__func__, accessType); 384668a58b8STom Eccles ASSERT_FALSE(path.empty()); 385668a58b8STom Eccles 386668a58b8STom Eccles accessType.read = true; 387668a58b8STom Eccles accessType.write = true; 388668a58b8STom Eccles accessType.execute = true; 389668a58b8STom Eccles std::int64_t res = callAccess(path, accessType); 390668a58b8STom Eccles 391668a58b8STom Eccles ASSERT_EQ(unlink(path.c_str()), 0); 392668a58b8STom Eccles 393*32403f79STom Eccles if (userSkipsPermissionChecks()) { 394*32403f79STom Eccles return; 395*32403f79STom Eccles } 396*32403f79STom Eccles 397668a58b8STom Eccles ASSERT_NE(res, 0); 398668a58b8STom Eccles } 399668a58b8STom Eccles 400668a58b8STom Eccles TEST(AccessTests, TestNotRWX1) { 401668a58b8STom Eccles AccessType accessType; 402668a58b8STom Eccles accessType.read = true; 403668a58b8STom Eccles accessType.write = false; 404668a58b8STom Eccles accessType.execute = false; 405668a58b8STom Eccles 406668a58b8STom Eccles std::string path = createTemporaryFile(__func__, accessType); 407668a58b8STom Eccles ASSERT_FALSE(path.empty()); 408668a58b8STom Eccles 409668a58b8STom Eccles accessType.read = true; 410668a58b8STom Eccles accessType.write = true; 411668a58b8STom Eccles accessType.execute = true; 412668a58b8STom Eccles std::int64_t res = callAccess(path, accessType); 413668a58b8STom Eccles 414668a58b8STom Eccles ASSERT_EQ(unlink(path.c_str()), 0); 415668a58b8STom Eccles 416*32403f79STom Eccles if (userSkipsPermissionChecks()) { 417*32403f79STom Eccles return; 418*32403f79STom Eccles } 419*32403f79STom Eccles 420668a58b8STom Eccles ASSERT_NE(res, 0); 421668a58b8STom Eccles } 422668a58b8STom Eccles 423668a58b8STom Eccles TEST(AccessTests, TestNotRWX2) { 424668a58b8STom Eccles AccessType accessType; 425668a58b8STom Eccles accessType.read = true; 426668a58b8STom Eccles accessType.write = true; 427668a58b8STom Eccles accessType.execute = false; 428668a58b8STom Eccles 429668a58b8STom Eccles std::string path = createTemporaryFile(__func__, accessType); 430668a58b8STom Eccles ASSERT_FALSE(path.empty()); 431668a58b8STom Eccles 432668a58b8STom Eccles accessType.read = true; 433668a58b8STom Eccles accessType.write = true; 434668a58b8STom Eccles accessType.execute = true; 435668a58b8STom Eccles std::int64_t res = callAccess(path, accessType); 436668a58b8STom Eccles 437668a58b8STom Eccles ASSERT_EQ(unlink(path.c_str()), 0); 438668a58b8STom Eccles 439*32403f79STom Eccles if (userSkipsPermissionChecks()) { 440*32403f79STom Eccles return; 441*32403f79STom Eccles } 442*32403f79STom Eccles 443668a58b8STom Eccles ASSERT_NE(res, 0); 444668a58b8STom Eccles } 445668a58b8STom Eccles 446668a58b8STom Eccles TEST(AccessTests, TestNotRWX3) { 447668a58b8STom Eccles AccessType accessType; 448668a58b8STom Eccles accessType.read = true; 449668a58b8STom Eccles accessType.write = false; 450668a58b8STom Eccles accessType.execute = true; 451668a58b8STom Eccles 452668a58b8STom Eccles std::string path = createTemporaryFile(__func__, accessType); 453668a58b8STom Eccles ASSERT_FALSE(path.empty()); 454668a58b8STom Eccles 455668a58b8STom Eccles accessType.read = true; 456668a58b8STom Eccles accessType.write = true; 457668a58b8STom Eccles accessType.execute = true; 458668a58b8STom Eccles std::int64_t res = callAccess(path, accessType); 459668a58b8STom Eccles 460668a58b8STom Eccles ASSERT_EQ(unlink(path.c_str()), 0); 461668a58b8STom Eccles 462*32403f79STom Eccles if (userSkipsPermissionChecks()) { 463*32403f79STom Eccles return; 464*32403f79STom Eccles } 465*32403f79STom Eccles 466668a58b8STom Eccles ASSERT_NE(res, 0); 467668a58b8STom Eccles } 468668a58b8STom Eccles 469668a58b8STom Eccles TEST(AccessTests, TestNotRWX4) { 470668a58b8STom Eccles AccessType accessType; 471668a58b8STom Eccles accessType.read = false; 472668a58b8STom Eccles accessType.write = true; 473668a58b8STom Eccles accessType.execute = true; 474668a58b8STom Eccles 475668a58b8STom Eccles std::string path = createTemporaryFile(__func__, accessType); 476668a58b8STom Eccles ASSERT_FALSE(path.empty()); 477668a58b8STom Eccles 478668a58b8STom Eccles accessType.read = true; 479668a58b8STom Eccles accessType.write = true; 480668a58b8STom Eccles accessType.execute = true; 481668a58b8STom Eccles std::int64_t res = callAccess(path, accessType); 482668a58b8STom Eccles 483668a58b8STom Eccles ASSERT_EQ(unlink(path.c_str()), 0); 484668a58b8STom Eccles 485*32403f79STom Eccles if (userSkipsPermissionChecks()) { 486*32403f79STom Eccles return; 487*32403f79STom Eccles } 488*32403f79STom Eccles 489668a58b8STom Eccles ASSERT_NE(res, 0); 490668a58b8STom Eccles } 491668a58b8STom Eccles 492668a58b8STom Eccles #endif // !_WIN32 493