1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
10 // UNSUPPORTED: no-filesystem
11 // UNSUPPORTED: availability-filesystem-missing
13 // Starting in Android N (API 24), SELinux policy prevents the shell user from
14 // creating a FIFO file.
15 // XFAIL: LIBCXX-ANDROID-FIXME && !android-device-api={{21|22|23}}
19 // file_status symlink_status(const path& p);
20 // file_status symlink_status(const path& p, error_code& ec) noexcept;
22 #include "filesystem_include.h"
24 #include "assert_macros.h"
25 #include "test_macros.h"
26 #include "filesystem_test_helper.h"
30 static void signature_test()
32 const path p
; ((void)p
);
33 std::error_code ec
; ((void)ec
);
34 ASSERT_NOT_NOEXCEPT(symlink_status(p
));
35 ASSERT_NOEXCEPT(symlink_status(p
, ec
));
38 static void test_symlink_status_not_found()
40 static_test_env static_env
;
41 const std::errc expect_errc
= std::errc::no_such_file_or_directory
;
45 for (auto& p
: cases
) {
46 std::error_code ec
= std::make_error_code(std::errc::address_in_use
);
47 // test non-throwing overload.
48 file_status st
= symlink_status(p
, ec
);
49 assert(ErrorIs(ec
, expect_errc
));
50 assert(st
.type() == file_type::not_found
);
51 assert(st
.permissions() == perms::unknown
);
52 // test throwing overload. It should not throw even though it reports
53 // that the file was not found.
54 TEST_DOES_NOT_THROW(st
= status(p
));
55 assert(st
.type() == file_type::not_found
);
56 assert(st
.permissions() == perms::unknown
);
60 // Windows doesn't support setting perms::none to trigger failures
61 // reading directories. Imaginary files under GetWindowsInaccessibleDir()
62 // produce no_such_file_or_directory, not the error codes this test checks
63 // for. Finally, status() for a too long file name doesn't return errors
65 #ifndef TEST_WIN_NO_FILESYSTEM_PERMS_NONE
66 static void test_symlink_status_cannot_resolve()
69 const path dir
= env
.create_dir("dir");
70 const path file_in_dir
= env
.create_file("dir/file", 42);
71 const path sym_in_dir
= env
.create_symlink("dir/file", "dir/bad_sym");
72 const path sym_points_in_dir
= env
.create_symlink("dir/file", "sym");
73 permissions(dir
, perms::none
);
75 const std::errc set_errc
= std::errc::address_in_use
;
76 const std::errc expect_errc
= std::errc::permission_denied
;
78 const path fail_cases
[] = {
79 file_in_dir
, sym_in_dir
81 for (auto& p
: fail_cases
)
83 { // test non-throwing case
84 std::error_code ec
= std::make_error_code(set_errc
);
85 file_status st
= symlink_status(p
, ec
);
86 assert(ErrorIs(ec
, expect_errc
));
87 assert(st
.type() == file_type::none
);
88 assert(st
.permissions() == perms::unknown
);
90 #ifndef TEST_HAS_NO_EXCEPTIONS
91 { // test throwing case
93 (void)symlink_status(p
);
94 } catch (filesystem_error
const& err
) {
95 assert(err
.path1() == p
);
96 assert(err
.path2() == "");
97 assert(ErrorIs(err
.code(), expect_errc
));
102 // Test that a symlink that points into a directory without read perms
103 // can be stat-ed using symlink_status
105 std::error_code ec
= std::make_error_code(set_errc
);
106 file_status st
= symlink_status(sym_points_in_dir
, ec
);
108 assert(st
.type() == file_type::symlink
);
109 assert(st
.permissions() != perms::unknown
);
110 // test non-throwing version
111 TEST_DOES_NOT_THROW(st
= symlink_status(sym_points_in_dir
));
112 assert(st
.type() == file_type::symlink
);
113 assert(st
.permissions() != perms::unknown
);
116 #endif // TEST_WIN_NO_FILESYSTEM_PERMS_NONE
119 static void symlink_status_file_types_test()
121 static_test_env static_env
;
125 file_type expect_type
;
127 {static_env
.BadSymlink
, file_type::symlink
},
128 {static_env
.File
, file_type::regular
},
129 {static_env
.SymlinkToFile
, file_type::symlink
},
130 {static_env
.Dir
, file_type::directory
},
131 {static_env
.SymlinkToDir
, file_type::symlink
},
132 // file_type::block files tested elsewhere
134 {static_env
.CharFile
, file_type::character
},
136 #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(_WIN32) // No support for domain sockets
137 {env
.create_socket("socket"), file_type::socket
},
140 {env
.create_fifo("fifo"), file_type::fifo
}
143 for (const auto& TC
: cases
) {
144 // test non-throwing case
145 std::error_code ec
= std::make_error_code(std::errc::address_in_use
);
146 file_status st
= symlink_status(TC
.p
, ec
);
148 assert(st
.type() == TC
.expect_type
);
149 assert(st
.permissions() != perms::unknown
);
150 // test throwing case
151 TEST_DOES_NOT_THROW(st
= symlink_status(TC
.p
));
152 assert(st
.type() == TC
.expect_type
);
153 assert(st
.permissions() != perms::unknown
);
157 static void test_block_file()
159 const path possible_paths
[] = {
160 "/dev/drive0", // Apple
162 "/dev/loop0" // Linux
163 // No FreeBSD files known
166 for (const path
& possible_p
: possible_paths
) {
168 if (exists(possible_p
, ec
)) {
174 // No possible path found.
179 // test non-throwing case
180 std::error_code ec
= std::make_error_code(std::errc::address_in_use
);
181 file_status st
= symlink_status(p
, ec
);
183 assert(st
.type() == file_type::block
);
184 assert(st
.permissions() != perms::unknown
);
185 // test throwing case
186 TEST_DOES_NOT_THROW(st
= symlink_status(p
));
187 assert(st
.type() == file_type::block
);
188 assert(st
.permissions() != perms::unknown
);
190 const path sym
= env
.make_env_path("sym");
191 create_symlink(p
, sym
);
192 { // test symlink to block file
193 // test non-throwing case
194 std::error_code ec
= std::make_error_code(std::errc::address_in_use
);
195 file_status st
= symlink_status(sym
, ec
);
197 assert(st
.type() == file_type::symlink
);
198 assert(st
.permissions() != perms::unknown
);
199 // test throwing case
200 TEST_DOES_NOT_THROW(st
= symlink_status(sym
));
201 assert(st
.type() == file_type::symlink
);
202 assert(st
.permissions() != perms::unknown
);
206 int main(int, char**) {
208 test_symlink_status_not_found();
209 #ifndef TEST_WIN_NO_FILESYSTEM_PERMS_NONE
210 test_symlink_status_cannot_resolve();
212 symlink_status_file_types_test();