Skip to content

Commit 1bd8fb8

Browse files
authored
native_readlink (#1205)
* fix nt no_block * Add readlinkat implementation for POSIX and Win32 APIs - Introduced `readlinkat` functionality in both POSIX and Win32 environments. - Added new `posix_readlinkat` and `win32_9xa_readlinkat` functions to handle symbolic link resolution. - Updated relevant headers and added error handling for invalid paths. - Enhanced the `dos_readlinkat_impl` to manage DOS-specific behavior for symbolic links. - Included a new example demonstrating the usage of `readlinkat` in `examples/0036.at/readlink.cc`. * Update function signature for path concatenation in Win32 platform header - Modified the signature of `concat_tlc_win32_9xa_path_uncheck_whether_exist` to improve clarity and maintain consistency in the codebase. * Refactor error handling in Win32 headers - Updated error handling in multiple Win32 header files to replace the error code `3221225530` with a more generic error code `3` for invalid DOS filenames. - This change enhances consistency across the error handling mechanisms in the Win32 platform implementation. * [fast_io] not finished * Refactor access mode handling in filesystem headers - Updated `dos_faccessat` and `native_faccessat` functions to correctly use the `access_how` parameter instead of `dos_at_flags` for mode handling. - Adjusted conditional checks in `nt_at.h` and `win32_9xa_at.h` to ensure proper evaluation of `symlink_nofollow` flag. - Improved clarity and consistency in the handling of file access modes across different platform implementations. * Enhance resource management in DOS filesystem handling - Added best-effort closing of file descriptors in the destructor and assignment operators to prevent resource leaks. - Improved safety checks for file descriptor validity before closing. - Ensured consistent handling of directory pointers and file descriptors across multiple methods. * Implement readlinkat functionality for NT filesystem - Added a new implementation of `nt_readlinkat_impl` to handle symbolic link resolution in the NT filesystem. - Enhanced error handling for symbolic links, including checks for reparse tags. - Refactored function signatures for consistency and clarity in the handling of directory handles and paths. - Improved overall structure and readability of the code in `nt_at.h`. * Update nt_at.h * fix
1 parent f3ebc0f commit 1bd8fb8

File tree

11 files changed

+496
-54
lines changed

11 files changed

+496
-54
lines changed

examples/0036.at/readlink.cc

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#include <fast_io.h>
2+
3+
int main(int argc, char **argv)
4+
{
5+
if (argc != 2)
6+
{
7+
if (argc == 0)
8+
{
9+
return 1;
10+
}
11+
::fast_io::io::perr("Usage: ", fast_io::mnp::os_c_str(*argv), " <symlink>\n");
12+
return 1;
13+
}
14+
15+
#if __cpp_exceptions
16+
try
17+
#endif
18+
{
19+
auto target{::fast_io::native_readlinkat<char>(::fast_io::at_fdcwd(), fast_io::mnp::os_c_str(argv[1]))};
20+
::fast_io::println(target);
21+
}
22+
#if __cpp_exceptions
23+
catch (fast_io::error e)
24+
{
25+
::fast_io::io::perrln(e);
26+
}
27+
#endif
28+
}
29+
30+

include/fast_io_hosted/filesystem/apis.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ enum class posix_api_22
88
renameat,
99
linkat
1010
};
11+
1112
enum class posix_api_12
1213
{
1314
symlinkat
1415
};
16+
1517
enum class posix_api_1x
1618
{
1719
faccessat,
@@ -24,4 +26,9 @@ enum class posix_api_1x
2426
unlinkat
2527
};
2628

29+
enum class posix_api_ct
30+
{
31+
readlinkat
32+
};
33+
2734
} // namespace fast_io::details

include/fast_io_hosted/filesystem/dos.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ class dos_directory_file FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE : public dos_
129129
{
130130
noexcept_call(::closedir, this->dirp.dirp);
131131
}
132+
if (this->dirp.fd != -1) [[likely]]
133+
{
134+
details::sys_close(this->dirp.fd);
135+
}
132136
this->dirp = newdir;
133137
return *this;
134138
}
@@ -147,6 +151,10 @@ class dos_directory_file FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE : public dos_
147151
{
148152
noexcept_call(::closedir, this->dirp.dirp);
149153
}
154+
if (this->dirp.fd != -1) [[likely]]
155+
{
156+
details::sys_close(this->dirp.fd);
157+
}
150158
this->dirp = other.release();
151159
return *this;
152160
}
@@ -157,16 +165,25 @@ class dos_directory_file FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE : public dos_
157165
{
158166
noexcept_call(::closedir, this->dirp.dirp);
159167
}
168+
if (this->dirp.fd != -1) [[likely]]
169+
{
170+
details::sys_close(this->dirp.fd);
171+
}
160172
this->dirp = dirp1;
161173
}
162174

163175
inline void close()
164176
{
165177
if (*this) [[likely]]
166178
{
179+
int fd_to_close{this->dirp.fd};
167180
int ret{noexcept_call(::closedir, this->dirp.dirp)};
168181
this->dirp.dirp = nullptr;
169182
this->dirp.fd = -1;
183+
if (fd_to_close != -1)
184+
{
185+
details::sys_close(fd_to_close);
186+
}
170187
if (ret == -1)
171188
{
172189
throw_posix_error();
@@ -180,6 +197,11 @@ class dos_directory_file FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE : public dos_
180197
{
181198
noexcept_call(::closedir, this->dirp.dirp);
182199
}
200+
if (this->dirp.fd != -1) [[likely]]
201+
{
202+
// best-effort close for fd; ignore failures in destructor
203+
details::sys_close(this->dirp.fd);
204+
}
183205
}
184206
};
185207

include/fast_io_hosted/filesystem/dos_at.h

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,26 @@ inline auto dos1x_api_dispatcher(int dirfd, char const *path, Args... args)
263263
}
264264
}
265265

266+
template <::std::integral char_type>
267+
inline ::fast_io::details::basic_ct_string<char_type> dos_readlinkat_impl(int dirfd, char const *pathname)
268+
{
269+
// DOS does not support readlink, so you must first verify its validity before throwing a einval exception (not symlink).
270+
::fast_io::system_call_throw_error(::fast_io::posix::my_dos_access(::fast_io::details::my_dos_concat_tlc_path(dirfd, pathname).c_str(), 0));
271+
272+
throw_posix_error(EINVAL);
273+
274+
return {};
275+
}
276+
277+
template <::std::integral char_type, posix_api_ct dsp, typename... Args>
278+
inline auto dosct_api_dispatcher(int dirfd, char const *path, Args... args)
279+
{
280+
if constexpr (dsp == ::fast_io::details::posix_api_ct::readlinkat)
281+
{
282+
return dos_readlinkat_impl<char_type>(dirfd, path, args...);
283+
}
284+
}
285+
266286
template <posix_api_22 dsp, ::fast_io::constructible_to_os_c_str old_path_type,
267287
::fast_io::constructible_to_os_c_str new_path_type, typename... Args>
268288
inline auto dos_deal_with22(int olddirfd, old_path_type const &oldpath, int newdirfd, new_path_type const &newpath, Args... args)
@@ -293,6 +313,12 @@ inline auto dos_deal_with1x(int dirfd, path_type const &path, Args... args)
293313
return ::fast_io::posix_api_common(path, [&](char const *path_c_str) { return dos1x_api_dispatcher<dsp>(dirfd, path_c_str, args...); });
294314
}
295315

316+
template <::std::integral char_type, posix_api_ct dsp, ::fast_io::constructible_to_os_c_str path_type, typename... Args>
317+
inline auto dos_deal_withct(int dirfd, path_type const &path, Args... args)
318+
{
319+
return ::fast_io::posix_api_common(path, [&](char const *path_c_str) { return dosct_api_dispatcher<char_type, dsp>(dirfd, path_c_str, args...); });
320+
}
321+
296322
} // namespace details
297323

298324
template <::fast_io::constructible_to_os_c_str old_path_type, ::fast_io::constructible_to_os_c_str new_path_type>
@@ -337,17 +363,17 @@ inline void native_symlinkat(old_path_type const &oldpath, posix_at_entry newent
337363

338364

339365
template <::fast_io::constructible_to_os_c_str path_type>
340-
inline void dos_faccessat(posix_at_entry ent, path_type const &path, [[maybe_unused]] access_how mode,
341-
dos_at_flags flags = dos_at_flags::symlink_nofollow)
366+
inline void dos_faccessat(posix_at_entry ent, path_type const &path, access_how mode,
367+
[[maybe_unused]] dos_at_flags flags = dos_at_flags::symlink_nofollow)
342368
{
343-
::fast_io::details::dos_deal_with1x<::fast_io::details::posix_api_1x::faccessat>(ent.fd, path, static_cast<int>(flags));
369+
::fast_io::details::dos_deal_with1x<::fast_io::details::posix_api_1x::faccessat>(ent.fd, path, static_cast<int>(mode));
344370
}
345371

346372
template <::fast_io::constructible_to_os_c_str path_type>
347-
inline void native_faccessat(posix_at_entry ent, path_type const &path, [[maybe_unused]] access_how mode,
348-
dos_at_flags flags = dos_at_flags::symlink_nofollow)
373+
inline void native_faccessat(posix_at_entry ent, path_type const &path, access_how mode,
374+
[[maybe_unused]] dos_at_flags flags = dos_at_flags::symlink_nofollow)
349375
{
350-
::fast_io::details::dos_deal_with1x<::fast_io::details::posix_api_1x::faccessat>(ent.fd, path, static_cast<int>(flags));
376+
::fast_io::details::dos_deal_with1x<::fast_io::details::posix_api_1x::faccessat>(ent.fd, path, static_cast<int>(mode));
351377
}
352378

353379
template <::fast_io::constructible_to_os_c_str path_type>
@@ -448,4 +474,16 @@ inline void native_utimensat(posix_at_entry ent, path_type const &path, unix_tim
448474
last_modification_time);
449475
}
450476

477+
template <::std::integral char_type, ::fast_io::constructible_to_os_c_str path_type>
478+
inline ::fast_io::details::basic_ct_string<char_type> dos_readlinkat(posix_at_entry ent, path_type const &path)
479+
{
480+
return ::fast_io::details::dos_deal_withct<char_type, ::fast_io::details::posix_api_ct::readlinkat>(ent.fd, path);
481+
}
482+
483+
template <::std::integral char_type, ::fast_io::constructible_to_os_c_str path_type>
484+
inline ::fast_io::details::basic_ct_string<char_type> native_readlinkat(posix_at_entry ent, path_type const &path)
485+
{
486+
return ::fast_io::details::dos_deal_withct<char_type, ::fast_io::details::posix_api_ct::readlinkat>(ent.fd, path);
487+
}
488+
451489
} // namespace fast_io

include/fast_io_hosted/filesystem/fsutils.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,23 @@ find_dot_and_sep(char_type const *beg_ptr, ::std::size_t namlen) noexcept
6565
}
6666
}
6767

68+
template <::std::integral char_type>
69+
using basic_ct_string = ::fast_io::containers::basic_string<char_type, ::fast_io::native_global_allocator>;
70+
71+
template <::std::integral char_type, typename... Args>
72+
inline constexpr basic_ct_string<char_type> concat_ct(Args &&...args)
73+
{
74+
constexpr bool type_error{::fast_io::operations::defines::print_freestanding_okay<::fast_io::details::dummy_buffer_output_stream<char_type>,Args...>};
75+
if constexpr (type_error)
76+
{
77+
return ::fast_io::details::decay::basic_general_concat_phase1_decay_impl<false, char_type, ::fast_io::containers::basic_string<char_type, ::fast_io::native_global_allocator>>(
78+
io_print_forward<char_type>(io_print_alias(args))...);
79+
}
80+
else
81+
{
82+
static_assert(type_error, "some types are not printable, so we cannot concat ::fast_io::containers::basic_string<char_type>");
83+
return {};
84+
}
85+
}
86+
6887
} // namespace fast_io::details

0 commit comments

Comments
 (0)