1 //===----------------------------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // UNSUPPORTED: c++98, c++03 11 12 // <experimental/filesystem> 13 14 // void permissions(const path& p, perms prms); 15 // void permissions(const path& p, perms prms, std::error_code& ec) noexcept; 16 17 18 #include <experimental/filesystem> 19 20 #include "test_macros.h" 21 #include "rapid-cxx-test.hpp" 22 #include "filesystem_test_helper.hpp" 23 24 using namespace std::experimental::filesystem; 25 namespace fs = std::experimental::filesystem; 26 27 using PR = fs::perms; 28 29 TEST_SUITE(filesystem_permissions_test_suite) 30 31 TEST_CASE(test_signatures) 32 { 33 const path p; ((void)p); 34 const perms opts{}; ((void)opts); 35 std::error_code ec; ((void)ec); 36 ASSERT_NOT_NOEXCEPT(fs::permissions(p, opts)); 37 // Not noexcept because of narrow contract 38 LIBCPP_ONLY( 39 ASSERT_NOT_NOEXCEPT(fs::permissions(p, opts, ec))); 40 } 41 42 TEST_CASE(test_error_reporting) 43 { 44 auto checkThrow = [](path const& f, fs::perms opts, const std::error_code& ec) 45 { 46 #ifndef TEST_HAS_NO_EXCEPTIONS 47 try { 48 fs::permissions(f, opts); 49 return false; 50 } catch (filesystem_error const& err) { 51 return err.path1() == f 52 && err.path2() == "" 53 && err.code() == ec; 54 } 55 #else 56 ((void)f); ((void)opts); ((void)ec); 57 return true; 58 #endif 59 }; 60 61 scoped_test_env env; 62 const path dne = env.make_env_path("dne"); 63 const path dne_sym = env.create_symlink(dne, "dne_sym"); 64 { // !exists 65 std::error_code ec; 66 fs::permissions(dne, fs::perms{}, ec); 67 TEST_REQUIRE(ec); 68 TEST_CHECK(checkThrow(dne, fs::perms{}, ec)); 69 } 70 { 71 std::error_code ec; 72 fs::permissions(dne_sym, fs::perms{}, ec); 73 TEST_REQUIRE(ec); 74 TEST_CHECK(checkThrow(dne_sym, fs::perms{}, ec)); 75 } 76 } 77 78 TEST_CASE(basic_permissions_test) 79 { 80 scoped_test_env env; 81 const path file = env.create_file("file1", 42); 82 const path dir = env.create_dir("dir1"); 83 const path file_for_sym = env.create_file("file2", 42); 84 const path sym = env.create_symlink(file_for_sym, "sym"); 85 const perms AP = perms::add_perms; 86 const perms RP = perms::remove_perms; 87 const perms NF = perms::symlink_nofollow; 88 struct TestCase { 89 path p; 90 perms set_perms; 91 perms expected; 92 } cases[] = { 93 // test file 94 {file, perms::none, perms::none}, 95 {file, perms::owner_all, perms::owner_all}, 96 {file, perms::group_all | AP, perms::owner_all | perms::group_all}, 97 {file, perms::group_all | RP, perms::owner_all}, 98 // test directory 99 {dir, perms::none, perms::none}, 100 {dir, perms::owner_all, perms::owner_all}, 101 {dir, perms::group_all | AP, perms::owner_all | perms::group_all}, 102 {dir, perms::group_all | RP, perms::owner_all}, 103 // test symlink without symlink_nofollow 104 {sym, perms::none, perms::none}, 105 {sym, perms::owner_all, perms::owner_all}, 106 {sym, perms::group_all | AP, perms::owner_all | perms::group_all}, 107 {sym, perms::group_all | RP , perms::owner_all}, 108 // test non-symlink with symlink_nofollow. The last test on file/dir 109 // will have set their permissions to perms::owner_all 110 {file, perms::group_all | AP | NF, perms::owner_all | perms::group_all}, 111 {dir, perms::group_all | AP | NF, perms::owner_all | perms::group_all} 112 }; 113 for (auto const& TC : cases) { 114 TEST_CHECK(status(TC.p).permissions() != TC.expected); 115 // Set the error code to ensure it's cleared. 116 std::error_code ec = std::make_error_code(std::errc::bad_address); 117 permissions(TC.p, TC.set_perms, ec); 118 TEST_CHECK(!ec); 119 auto pp = status(TC.p).permissions(); 120 TEST_CHECK(pp == TC.expected); 121 } 122 } 123 124 TEST_CASE(test_no_resolve_symlink_on_symlink) 125 { 126 scoped_test_env env; 127 const path file = env.create_file("file", 42); 128 const path sym = env.create_symlink(file, "sym"); 129 const auto file_perms = status(file).permissions(); 130 131 struct TestCase { 132 perms set_perms; 133 perms expected; // only expected on platform that support symlink perms. 134 } cases[] = { 135 {perms::owner_all, perms::owner_all}, 136 {perms::group_all | perms::add_perms, perms::owner_all | perms::group_all}, 137 {perms::owner_all | perms::remove_perms, perms::group_all}, 138 }; 139 for (auto const& TC : cases) { 140 #if defined(__APPLE__) || defined(__FreeBSD__) 141 // On OS X symlink permissions are supported. We should get an empty 142 // error code and the expected permissions. 143 const auto expected_link_perms = TC.expected; 144 std::error_code expected_ec; 145 #else 146 // On linux symlink permissions are not supported. The error code should 147 // be 'operation_not_supported' and the symlink permissions should be 148 // unchanged. 149 const auto expected_link_perms = symlink_status(sym).permissions(); 150 std::error_code expected_ec = std::make_error_code(std::errc::operation_not_supported); 151 #endif 152 std::error_code ec = std::make_error_code(std::errc::bad_address); 153 permissions(sym, TC.set_perms | perms::symlink_nofollow, ec); 154 TEST_CHECK(ec == expected_ec); 155 TEST_CHECK(status(file).permissions() == file_perms); 156 TEST_CHECK(symlink_status(sym).permissions() == expected_link_perms); 157 } 158 } 159 160 TEST_SUITE_END() 161