1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // REQUIRES: can-create-symlinks
10 // UNSUPPORTED: c++03, c++11, c++14
11 // UNSUPPORTED: no-filesystem
12 // UNSUPPORTED: availability-filesystem-missing
13 
14 // Starting in Android N (API 24), SELinux policy prevents the shell user from
15 // creating a FIFO file.
16 // XFAIL: LIBCXX-ANDROID-FIXME && !android-device-api={{21|22|23}}
17 
18 // <filesystem>
19 
20 // file_status status(const path& p);
21 // file_status status(const path& p, error_code& ec) noexcept;
22 
23 #include <filesystem>
24 
25 #include "assert_macros.h"
26 #include "test_macros.h"
27 #include "filesystem_test_helper.h"
28 namespace fs = std::filesystem;
29 using namespace fs;
30 
signature_test()31 static void signature_test()
32 {
33     const path p; ((void)p);
34     std::error_code ec; ((void)ec);
35     ASSERT_NOT_NOEXCEPT(status(p));
36     ASSERT_NOEXCEPT(status(p, ec));
37 }
38 
test_status_not_found()39 static void test_status_not_found()
40 {
41     static_test_env static_env;
42     const std::errc expect_errc = std::errc::no_such_file_or_directory;
43     const path cases[] {
44         static_env.DNE,
45         static_env.BadSymlink
46     };
47     for (auto& p : cases) {
48         std::error_code ec = std::make_error_code(std::errc::address_in_use);
49         // test non-throwing overload.
50         file_status st = status(p, ec);
51         assert(ErrorIs(ec, expect_errc));
52         assert(st.type() == file_type::not_found);
53         assert(st.permissions() == perms::unknown);
54         // test throwing overload. It should not throw even though it reports
55         // that the file was not found.
56         TEST_DOES_NOT_THROW(st = status(p));
57         assert(st.type() == file_type::not_found);
58         assert(st.permissions() == perms::unknown);
59     }
60 }
61 
62 // Windows doesn't support setting perms::none to trigger failures
63 // reading directories. Imaginary files under GetWindowsInaccessibleDir()
64 // produce no_such_file_or_directory, not the error codes this test checks
65 // for. Finally, status() for a too long file name doesn't return errors
66 // on windows.
67 #ifndef TEST_WIN_NO_FILESYSTEM_PERMS_NONE
test_status_cannot_resolve()68 static void test_status_cannot_resolve()
69 {
70     scoped_test_env env;
71     const path dir = env.create_dir("dir");
72     const path file = env.create_file("dir/file", 42);
73     const path sym = env.create_symlink("dir/file", "sym");
74     permissions(dir, perms::none);
75 
76     const std::errc set_errc = std::errc::address_in_use;
77     const std::errc perm_errc = std::errc::permission_denied;
78     const std::errc name_too_long_errc = std::errc::filename_too_long;
79 
80     struct TestCase {
81       path p;
82       std::errc expect_errc;
83     } const TestCases[] = {
84       {file, perm_errc},
85       {sym, perm_errc},
86       {path(std::string(2500, 'a')), name_too_long_errc}
87     };
88     for (auto& TC : TestCases)
89     {
90         { // test non-throwing case
91             std::error_code ec = std::make_error_code(set_errc);
92             file_status st = status(TC.p, ec);
93             assert(ErrorIs(ec, TC.expect_errc));
94             assert(st.type() == file_type::none);
95             assert(st.permissions() == perms::unknown);
96         }
97 #ifndef TEST_HAS_NO_EXCEPTIONS
98         { // test throwing case
99             try {
100                 status(TC.p);
101             } catch (filesystem_error const& err) {
102                 assert(err.path1() == TC.p);
103                 assert(err.path2() == "");
104                 assert(ErrorIs(err.code(), TC.expect_errc));
105             }
106         }
107 #endif
108     }
109 }
110 #endif // TEST_WIN_NO_FILESYSTEM_PERMS_NONE
111 
status_file_types_test()112 static void status_file_types_test()
113 {
114     static_test_env static_env;
115     scoped_test_env env;
116     struct TestCase {
117       path p;
118       file_type expect_type;
119     } cases[] = {
120         {static_env.File, file_type::regular},
121         {static_env.SymlinkToFile, file_type::regular},
122         {static_env.Dir, file_type::directory},
123         {static_env.SymlinkToDir, file_type::directory},
124         // file_type::block files tested elsewhere
125 #ifndef _WIN32
126         {static_env.CharFile, file_type::character},
127 #endif
128 #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(_WIN32) // No support for domain sockets
129         {env.create_socket("socket"), file_type::socket},
130 #endif
131 #ifndef _WIN32
132         {env.create_fifo("fifo"), file_type::fifo}
133 #endif
134     };
135     for (const auto& TC : cases) {
136         // test non-throwing case
137         std::error_code ec = std::make_error_code(std::errc::address_in_use);
138         file_status st = status(TC.p, ec);
139         assert(!ec);
140         assert(st.type() == TC.expect_type);
141         assert(st.permissions() != perms::unknown);
142         // test throwing case
143         TEST_DOES_NOT_THROW(st = status(TC.p));
144         assert(st.type() == TC.expect_type);
145         assert(st.permissions() != perms::unknown);
146     }
147 }
148 
test_block_file()149 static void test_block_file()
150 {
151     const path possible_paths[] = {
152         "/dev/drive0", // Apple
153         "/dev/sda",
154         "/dev/loop0"
155     };
156     path p;
157     for (const path& possible_p : possible_paths) {
158         std::error_code ec;
159         if (exists(possible_p, ec)) {
160             p = possible_p;
161             break;
162         }
163     }
164     if (p == path{}) {
165         // No possible path found.
166         return;
167     }
168     // test non-throwing case
169     std::error_code ec = std::make_error_code(std::errc::address_in_use);
170     file_status st = status(p, ec);
171     assert(!ec);
172     assert(st.type() == file_type::block);
173     assert(st.permissions() != perms::unknown);
174     // test throwing case
175     TEST_DOES_NOT_THROW(st = status(p));
176     assert(st.type() == file_type::block);
177     assert(st.permissions() != perms::unknown);
178 }
179 
main(int,char **)180 int main(int, char**) {
181     signature_test();
182     test_status_not_found();
183 #ifndef TEST_WIN_NO_FILESYSTEM_PERMS_NONE
184     test_status_cannot_resolve();
185 #endif
186     status_file_types_test();
187     test_block_file();
188 
189     return 0;
190 }
191