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 // <filesystem>
13
14 // void permissions(const path& p, perms prms,
15 // perm_options opts = perm_options::replace);
16 // void permissions(const path& p, perms prms, std::error_code& ec) noexcept;
17 // void permissions(const path& p, perms prms, perm_options opts, std::error_code);
18
19
20
21 #include "filesystem_include.hpp"
22
23 #include "test_macros.h"
24 #include "rapid-cxx-test.hpp"
25 #include "filesystem_test_helper.hpp"
26
27 using namespace fs;
28
29 using PR = fs::perms;
30
31 TEST_SUITE(filesystem_permissions_test_suite)
32
TEST_CASE(test_signatures)33 TEST_CASE(test_signatures)
34 {
35 const path p; ((void)p);
36 const perms pr{}; ((void)pr);
37 const perm_options opts{}; ((void)opts);
38 std::error_code ec; ((void)ec);
39 ASSERT_NOT_NOEXCEPT(fs::permissions(p, pr));
40 ASSERT_NOT_NOEXCEPT(fs::permissions(p, pr, opts));
41 ASSERT_NOEXCEPT(fs::permissions(p, pr, ec));
42 ASSERT_NOT_NOEXCEPT(fs::permissions(p, pr, opts, ec));
43 }
44
TEST_CASE(test_error_reporting)45 TEST_CASE(test_error_reporting)
46 {
47 auto checkThrow = [](path const& f, fs::perms opts,
48 const std::error_code& ec)
49 {
50 #ifndef TEST_HAS_NO_EXCEPTIONS
51 try {
52 fs::permissions(f, opts);
53 return false;
54 } catch (filesystem_error const& err) {
55 return err.path1() == f
56 && err.path2() == ""
57 && err.code() == ec;
58 }
59 #else
60 ((void)f); ((void)opts); ((void)ec);
61 return true;
62 #endif
63 };
64
65 scoped_test_env env;
66 const path dne = env.make_env_path("dne");
67 const path dne_sym = env.create_symlink(dne, "dne_sym");
68 { // !exists
69 std::error_code ec = GetTestEC();
70 fs::permissions(dne, fs::perms{}, ec);
71 TEST_REQUIRE(ec);
72 TEST_CHECK(ec != GetTestEC());
73 TEST_CHECK(checkThrow(dne, fs::perms{}, ec));
74 }
75 {
76 std::error_code ec = GetTestEC();
77 fs::permissions(dne_sym, fs::perms{}, ec);
78 TEST_REQUIRE(ec);
79 TEST_CHECK(ec != GetTestEC());
80 TEST_CHECK(checkThrow(dne_sym, fs::perms{}, ec));
81 }
82 }
83
TEST_CASE(basic_permissions_test)84 TEST_CASE(basic_permissions_test)
85 {
86 scoped_test_env env;
87 const path file = env.create_file("file1", 42);
88 const path dir = env.create_dir("dir1");
89 const path file_for_sym = env.create_file("file2", 42);
90 const path sym = env.create_symlink(file_for_sym, "sym");
91 const perm_options AP = perm_options::add;
92 const perm_options RP = perm_options::remove;
93 const perm_options NF = perm_options::nofollow;
94 struct TestCase {
95 path p;
96 perms set_perms;
97 perms expected;
98 perm_options opts;
99 TestCase(path xp, perms xperms, perms xexpect,
100 perm_options xopts = perm_options::replace)
101 : p(xp), set_perms(xperms), expected(xexpect), opts(xopts) {}
102 } cases[] = {
103 // test file
104 {file, perms::none, perms::none},
105 {file, perms::owner_all, perms::owner_all},
106 {file, perms::group_all, perms::owner_all | perms::group_all, AP},
107 {file, perms::group_all, perms::owner_all, RP},
108 // test directory
109 {dir, perms::none, perms::none},
110 {dir, perms::owner_all, perms::owner_all},
111 {dir, perms::group_all, perms::owner_all | perms::group_all, AP},
112 {dir, perms::group_all, perms::owner_all, RP},
113 // test symlink without symlink_nofollow
114 {sym, perms::none, perms::none},
115 {sym, perms::owner_all, perms::owner_all},
116 {sym, perms::group_all, perms::owner_all | perms::group_all, AP},
117 {sym, perms::group_all, perms::owner_all, RP},
118 // test non-symlink with symlink_nofollow. The last test on file/dir
119 // will have set their permissions to perms::owner_all
120 {file, perms::group_all, perms::owner_all | perms::group_all, AP | NF},
121 {dir, perms::group_all, perms::owner_all | perms::group_all, AP | NF}
122 };
123 for (auto const& TC : cases) {
124 TEST_CHECK(status(TC.p).permissions() != TC.expected);
125 {
126 std::error_code ec = GetTestEC();
127 permissions(TC.p, TC.set_perms, TC.opts, ec);
128 TEST_CHECK(!ec);
129 auto pp = status(TC.p).permissions();
130 TEST_CHECK(pp == TC.expected);
131 }
132 if (TC.opts == perm_options::replace) {
133 std::error_code ec = GetTestEC();
134 permissions(TC.p, TC.set_perms, ec);
135 TEST_CHECK(!ec);
136 auto pp = status(TC.p).permissions();
137 TEST_CHECK(pp == TC.expected);
138 }
139 }
140 }
141
TEST_CASE(test_no_resolve_symlink_on_symlink)142 TEST_CASE(test_no_resolve_symlink_on_symlink)
143 {
144 scoped_test_env env;
145 const path file = env.create_file("file", 42);
146 const path sym = env.create_symlink(file, "sym");
147 const auto file_perms = status(file).permissions();
148
149 struct TestCase {
150 perms set_perms;
151 perms expected; // only expected on platform that support symlink perms.
152 perm_options opts = perm_options::replace;
153 TestCase(perms xperms, perms xexpect,
154 perm_options xopts = perm_options::replace)
155 : set_perms(xperms), expected(xexpect), opts(xopts) {}
156 } cases[] = {
157 {perms::owner_all, perms::owner_all},
158 {perms::group_all, perms::owner_all | perms::group_all, perm_options::add},
159 {perms::owner_all, perms::group_all, perm_options::remove},
160 };
161 for (auto const& TC : cases) {
162 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
163 defined(__ANDROID__)
164 // On OS X symlink permissions are supported. We should get an empty
165 // error code and the expected permissions.
166 const auto expected_link_perms = TC.expected;
167 std::error_code expected_ec;
168 #else
169 // On linux symlink permissions are not supported. The error code should
170 // be 'operation_not_supported' and the symlink permissions should be
171 // unchanged.
172 const auto expected_link_perms = symlink_status(sym).permissions();
173 std::error_code expected_ec = std::make_error_code(std::errc::operation_not_supported);
174 #endif
175 std::error_code ec = GetTestEC();
176 permissions(sym, TC.set_perms, TC.opts | perm_options::nofollow, ec);
177 TEST_CHECK(ec == expected_ec);
178 TEST_CHECK(status(file).permissions() == file_perms);
179 TEST_CHECK(symlink_status(sym).permissions() == expected_link_perms);
180 }
181 }
182
183 TEST_SUITE_END()
184