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"
28namespace fs = std::filesystem;
29using namespace fs;
30
31static void signature_test()
32{
33 const path p; ((void)p);
34 std::error_code ec; ((void)ec);
35 ASSERT_NOT_NOEXCEPT(status(p: p));
36 ASSERT_NOEXCEPT(status(p: p, ec&: ec));
37}
38
39static 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
68static 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(p: dir, prms: 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 {.p: file, .expect_errc: perm_errc},
85 {.p: sym, .expect_errc: perm_errc},
86 {.p: path(std::string(2500, 'a')), .expect_errc: 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
112static 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
149static 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(p: possible_p, ec&: 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(e: std::errc::address_in_use);
170 file_status st = status(p: p, ec&: 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: p));
176 assert(st.type() == file_type::block);
177 assert(st.permissions() != perms::unknown);
178}
179
180int 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

source code of libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.status/status.pass.cpp