diff --git a/include/fast_io_hosted/filesystem/native.h b/include/fast_io_hosted/filesystem/native.h index c95da769..9d72dccf 100644 --- a/include/fast_io_hosted/filesystem/native.h +++ b/include/fast_io_hosted/filesystem/native.h @@ -10,6 +10,7 @@ #if (defined(_WIN32) || defined(__CYGWIN__)) #if defined(_WIN32_WINDOWS) +#include "../../fast_io_dsal/string.h" #include "win9x.h" #include "win9x_at.h" #else diff --git a/include/fast_io_hosted/filesystem/win9x.h b/include/fast_io_hosted/filesystem/win9x.h index 73b4b866..7675506b 100644 --- a/include/fast_io_hosted/filesystem/win9x.h +++ b/include/fast_io_hosted/filesystem/win9x.h @@ -1 +1,100 @@ #pragma once + +namespace fast_io +{ + +struct win9x_DIR +{ + void *d_handle{}; + file_type d_type{}; + ::std::uint_least64_t d_ino{}; + ::fast_io::string path{}; +}; + +namespace win32::details +{ +inline ::fast_io::string get_file_full_path_from_path_handle(void *fhandle) +{ + char pszFilename[261]; + + void *hFileMap{::fast_io::win32::CreateFileMappingA(fhandle, nullptr, 0x10000000 | 0x02, 0, 1, nullptr)}; + if (!hFileMap) [[unlikely]] + { + throw_win32_error(); + } + handle_guard hg1{hFileMap}; + + // Create a file mapping to get the file name. + void *pMem{::fast_io::win32::MapViewOfFile(hFileMap, 0x04, 0, 0, 1)}; + if (!pMem) [[unlikely]] + { + throw_win32_error(); + } + + if (! +#if !defined(_WIN32_WINNT) || _WIN32_WINNT >= 0x601 + ::fast_io::win32::K32GetMappedFileNameA( +#else + ::fast_io::win32::GetMappedFileNameA( +#endif + reinterpret_cast(static_cast<::std::ptrdiff_t>(-1)), + pMem, + pszFilename, + 260)) [[unlikely]] + { + throw_win32_error(); + } + map_guard mg1{pMem}; + + mg1.clear(); + hg1.clear(); + + // change nt path to dos path (9x) + auto address_begin{pszFilename}; + + // change nt path to dos path + auto k32_module{::fast_io::win32::GetModuleHandleA("Kernel32.dll")}; + if (k32_module) + { + using QueryDosDeviceA_t = ::std::uint_least32_t (*)(char const *, char *, ::std::uint_least32_t) noexcept; + + // win95 may not have this function, need check (?) + auto QueryDosDeviceA_p{reinterpret_cast(::fast_io::win32::GetProcAddress(k32_module, "QueryDosDeviceA"))}; + if (QueryDosDeviceA_p) + { + if (pszFilename[0] == '\\') + { + char DosDevice[4]{0, ':', 0, 0}; + char NtPath[64]; + char *RetStr{}; + ::std::size_t NtPathLen{}; + for (char i{65}; i < static_cast(26 + 65); i++) + { + DosDevice[0] = i; + if (QueryDosDeviceA_p(DosDevice, NtPath, 64)) + { + NtPathLen = ::fast_io::cstr_len(NtPath); + + if (::fast_io::freestanding::my_memcmp(pszFilename, NtPath, NtPathLen * sizeof(char)) == 0) [[unlikely]] + { + goto next2; + } + } + } + throw_win32_error(0x3); + next2: + address_begin += NtPathLen - 2; + address_begin[0] = DosDevice[0]; + address_begin[1] = ':'; + } + } + } +} + +} // namespace win32::details + +inline win9x_DIR *set_win9x_dirent(win9x_DIR *entry, bool start) +{ +} + +} // namespace fast_io diff --git a/include/fast_io_hosted/platforms/nt.h b/include/fast_io_hosted/platforms/nt.h index bbb5d232..7e02ed5a 100644 --- a/include/fast_io_hosted/platforms/nt.h +++ b/include/fast_io_hosted/platforms/nt.h @@ -1043,188 +1043,6 @@ inline void truncate(basic_nt_family_io_observer handle, ::std: { ::fast_io::win32::nt::details::nt_truncate_impl(handle.handle, newfilesize); } -#if 0 -template -inline posix_file_status status(basic_nt_family_io_observer handle) -{ - return ::fast_io::win32::nt::details::nt_status_impl(handle.handle); -} -#endif - -template -struct nt_family_file_lock -{ - void *handle{}; - template <::std::signed_integral int_type> - requires(sizeof(int_type) >= sizeof(::std::int_least64_t)) - inline void lock(basic_flock_request &__restrict t) - { - ::fast_io::win32::nt::details::nt_family_file_lock_impl(this->handle, t); - } - template <::std::signed_integral int_type> - requires(sizeof(int_type) >= sizeof(::std::int_least64_t)) - inline void unlock(basic_flock_request &__restrict t) noexcept - { - ::fast_io::win32::nt::details::nt_family_file_unlock_impl(this->handle, t); - } - template <::std::signed_integral int_type> - requires(sizeof(int_type) >= sizeof(::std::int_least64_t)) - inline bool try_lock(basic_flock_request &__restrict t) noexcept - { - return ::fast_io::win32::nt::details::nt_family_file_try_lock_impl(this->handle, t); - } -}; - -using nt_file_lock = nt_family_file_lock; -using zw_file_lock = nt_family_file_lock; - -template -inline constexpr nt_family_file_lock file_lock(basic_nt_family_io_observer niob) noexcept -{ - return {niob}; -} - -template -struct -#if __has_cpp_attribute(clang::trivially_relocatable) - [[clang::trivially_relocatable]] -#endif - nt_family_file_factory -{ - using native_handle_type = void *; - void *handle{}; - explicit constexpr nt_family_file_factory(void *hd) noexcept - : handle(hd) {}; - nt_family_file_factory(nt_family_file_factory const &) = delete; - nt_family_file_factory &operator=(nt_family_file_factory const &) = delete; - ~nt_family_file_factory() - { - if (handle) [[likely]] - { - ::fast_io::win32::nt::nt_close(this->handle); - } - } -}; - -using nt_file_factory = nt_family_file_factory; -using zw_file_factory = nt_family_file_factory; - -template -class basic_nt_family_file : public basic_nt_family_io_observer -{ -public: - using typename basic_nt_family_io_observer::char_type; - using typename basic_nt_family_io_observer::input_char_type; - using typename basic_nt_family_io_observer::output_char_type; - using typename basic_nt_family_io_observer::native_handle_type; - using file_factory_type = nt_family_file_factory; - constexpr basic_nt_family_file() noexcept = default; - constexpr basic_nt_family_file(basic_nt_family_io_observer) noexcept = delete; - constexpr basic_nt_family_file &operator=(basic_nt_family_io_observer) noexcept = delete; - - template - requires ::std::same_as> - explicit constexpr basic_nt_family_file(native_hd hd) noexcept - : basic_nt_family_io_observer{hd} - { - } - constexpr basic_nt_family_file(decltype(nullptr)) noexcept = delete; - explicit constexpr basic_nt_family_file(nt_family_file_factory &&hd) noexcept - : basic_nt_family_io_observer{hd} - { - hd.handle = nullptr; - } - explicit basic_nt_family_file(io_dup_t, basic_nt_family_io_observer wiob) - : basic_nt_family_io_observer{ - ::fast_io::win32::nt::details::nt_dup_impl(wiob.handle)} - { - } - explicit basic_nt_family_file(nt_fs_dirent fsdirent, open_mode om, perms pm = static_cast(436)) - : basic_nt_family_io_observer{ - ::fast_io::win32::nt::details::nt_family_create_file_fs_dirent_impl(fsdirent.handle, fsdirent.filename.c_str(), fsdirent.filename.size(), {om, pm})} - { - } - template <::fast_io::constructible_to_os_c_str T> - explicit basic_nt_family_file(T const &t, open_mode om, perms pm = static_cast(436)) - : basic_nt_family_io_observer{ - ::fast_io::win32::nt::details::nt_create_file_impl(t, {om, pm})} - { - } - template <::fast_io::constructible_to_os_c_str T> - explicit basic_nt_family_file(nt_at_entry ent, T const &t, open_mode om, perms pm = static_cast(436)) - : basic_nt_family_io_observer{ - ::fast_io::win32::nt::details::nt_create_file_at_impl(ent.handle, t, {om, pm})} - { - } - - template <::fast_io::constructible_to_os_c_str T> - explicit basic_nt_family_file(io_kernel_t, T const &t, open_mode om, perms pm = static_cast(436)) - : basic_nt_family_io_observer{ - ::fast_io::win32::nt::details::nt_create_file_kernel_impl(t, {om, pm})} - { - } - template <::fast_io::constructible_to_os_c_str T> - explicit basic_nt_family_file(io_kernel_t, nt_at_entry ent, T const &t, open_mode om, - perms pm = static_cast(436)) - : basic_nt_family_io_observer{ - ::fast_io::win32::nt::details::nt_create_file_at_impl(ent.handle, t, - {om, pm})} - { - } - - void close() - { - if (this->handle) [[likely]] - { - auto status{::fast_io::win32::nt::nt_close(this->handle)}; - this->handle = nullptr; // POSIX standard says we should never call close(2) again even close syscall fails - if (status) [[unlikely]] - { - throw_nt_error(status); - } - } - } - void reset(native_handle_type newhandle = nullptr) noexcept - { - if (this->handle) [[likely]] - { - ::fast_io::win32::nt::nt_close(this->handle); - } - this->handle = newhandle; - } - basic_nt_family_file(basic_nt_family_file const &other) - : basic_nt_family_io_observer( - ::fast_io::win32::nt::details::nt_dup_impl(other.handle)) - { - } - basic_nt_family_file &operator=(basic_nt_family_file const &other) - { - this->handle = ::fast_io::win32::nt::details::nt_dup2_impl(other.handle, this->handle); - return *this; - } - constexpr basic_nt_family_file(basic_nt_family_file &&__restrict other) noexcept - : basic_nt_family_io_observer{other.handle} - { - other.handle = nullptr; - } - basic_nt_family_file &operator=(basic_nt_family_file &&__restrict other) noexcept - { - if (this->handle) [[likely]] - { - ::fast_io::win32::nt::nt_close(this->handle); - } - this->handle = other.handle; - other.handle = nullptr; - return *this; - } - ~basic_nt_family_file() - { - if (this->handle) [[likely]] - { - ::fast_io::win32::nt::nt_close(this->handle); - } - } -}; namespace win32::nt::details { @@ -1427,6 +1245,181 @@ inline posix_file_status status(basic_nt_family_io_observer wio return win32::nt::details::nt_status_impl(wiob.handle); } +template +struct nt_family_file_lock +{ + void *handle{}; + template <::std::signed_integral int_type> + requires(sizeof(int_type) >= sizeof(::std::int_least64_t)) + inline void lock(basic_flock_request &__restrict t) + { + ::fast_io::win32::nt::details::nt_family_file_lock_impl(this->handle, t); + } + template <::std::signed_integral int_type> + requires(sizeof(int_type) >= sizeof(::std::int_least64_t)) + inline void unlock(basic_flock_request &__restrict t) noexcept + { + ::fast_io::win32::nt::details::nt_family_file_unlock_impl(this->handle, t); + } + template <::std::signed_integral int_type> + requires(sizeof(int_type) >= sizeof(::std::int_least64_t)) + inline bool try_lock(basic_flock_request &__restrict t) noexcept + { + return ::fast_io::win32::nt::details::nt_family_file_try_lock_impl(this->handle, t); + } +}; + +using nt_file_lock = nt_family_file_lock; +using zw_file_lock = nt_family_file_lock; + +template +inline constexpr nt_family_file_lock file_lock(basic_nt_family_io_observer niob) noexcept +{ + return {niob}; +} + +template +struct +#if __has_cpp_attribute(clang::trivially_relocatable) + [[clang::trivially_relocatable]] +#endif + nt_family_file_factory +{ + using native_handle_type = void *; + void *handle{}; + explicit constexpr nt_family_file_factory(void *hd) noexcept + : handle(hd) {}; + nt_family_file_factory(nt_family_file_factory const &) = delete; + nt_family_file_factory &operator=(nt_family_file_factory const &) = delete; + ~nt_family_file_factory() + { + if (handle) [[likely]] + { + ::fast_io::win32::nt::nt_close(this->handle); + } + } +}; + +using nt_file_factory = nt_family_file_factory; +using zw_file_factory = nt_family_file_factory; + +template +class basic_nt_family_file : public basic_nt_family_io_observer +{ +public: + using typename basic_nt_family_io_observer::char_type; + using typename basic_nt_family_io_observer::input_char_type; + using typename basic_nt_family_io_observer::output_char_type; + using typename basic_nt_family_io_observer::native_handle_type; + using file_factory_type = nt_family_file_factory; + constexpr basic_nt_family_file() noexcept = default; + constexpr basic_nt_family_file(basic_nt_family_io_observer) noexcept = delete; + constexpr basic_nt_family_file &operator=(basic_nt_family_io_observer) noexcept = delete; + + template + requires ::std::same_as> + explicit constexpr basic_nt_family_file(native_hd hd) noexcept + : basic_nt_family_io_observer{hd} + { + } + constexpr basic_nt_family_file(decltype(nullptr)) noexcept = delete; + explicit constexpr basic_nt_family_file(nt_family_file_factory &&hd) noexcept + : basic_nt_family_io_observer{hd} + { + hd.handle = nullptr; + } + explicit basic_nt_family_file(io_dup_t, basic_nt_family_io_observer wiob) + : basic_nt_family_io_observer{ + ::fast_io::win32::nt::details::nt_dup_impl(wiob.handle)} + { + } + explicit basic_nt_family_file(nt_fs_dirent fsdirent, open_mode om, perms pm = static_cast(436)) + : basic_nt_family_io_observer{ + ::fast_io::win32::nt::details::nt_family_create_file_fs_dirent_impl(fsdirent.handle, fsdirent.filename.c_str(), fsdirent.filename.size(), {om, pm})} + { + } + template <::fast_io::constructible_to_os_c_str T> + explicit basic_nt_family_file(T const &t, open_mode om, perms pm = static_cast(436)) + : basic_nt_family_io_observer{ + ::fast_io::win32::nt::details::nt_create_file_impl(t, {om, pm})} + { + } + template <::fast_io::constructible_to_os_c_str T> + explicit basic_nt_family_file(nt_at_entry ent, T const &t, open_mode om, perms pm = static_cast(436)) + : basic_nt_family_io_observer{ + ::fast_io::win32::nt::details::nt_create_file_at_impl(ent.handle, t, {om, pm})} + { + } + + template <::fast_io::constructible_to_os_c_str T> + explicit basic_nt_family_file(io_kernel_t, T const &t, open_mode om, perms pm = static_cast(436)) + : basic_nt_family_io_observer{ + ::fast_io::win32::nt::details::nt_create_file_kernel_impl(t, {om, pm})} + { + } + template <::fast_io::constructible_to_os_c_str T> + explicit basic_nt_family_file(io_kernel_t, nt_at_entry ent, T const &t, open_mode om, + perms pm = static_cast(436)) + : basic_nt_family_io_observer{ + ::fast_io::win32::nt::details::nt_create_file_at_impl(ent.handle, t, + {om, pm})} + { + } + + void close() + { + if (this->handle) [[likely]] + { + auto status{::fast_io::win32::nt::nt_close(this->handle)}; + this->handle = nullptr; // POSIX standard says we should never call close(2) again even close syscall fails + if (status) [[unlikely]] + { + throw_nt_error(status); + } + } + } + void reset(native_handle_type newhandle = nullptr) noexcept + { + if (this->handle) [[likely]] + { + ::fast_io::win32::nt::nt_close(this->handle); + } + this->handle = newhandle; + } + basic_nt_family_file(basic_nt_family_file const &other) + : basic_nt_family_io_observer( + ::fast_io::win32::nt::details::nt_dup_impl(other.handle)) + { + } + basic_nt_family_file &operator=(basic_nt_family_file const &other) + { + this->handle = ::fast_io::win32::nt::details::nt_dup2_impl(other.handle, this->handle); + return *this; + } + constexpr basic_nt_family_file(basic_nt_family_file &&__restrict other) noexcept + : basic_nt_family_io_observer{other.handle} + { + other.handle = nullptr; + } + basic_nt_family_file &operator=(basic_nt_family_file &&__restrict other) noexcept + { + if (this->handle) [[likely]] + { + ::fast_io::win32::nt::nt_close(this->handle); + } + this->handle = other.handle; + other.handle = nullptr; + return *this; + } + ~basic_nt_family_file() + { + if (this->handle) [[likely]] + { + ::fast_io::win32::nt::nt_close(this->handle); + } + } +}; + template <::std::integral char_type> using basic_nt_io_observer = basic_nt_family_io_observer; diff --git a/include/fast_io_hosted/platforms/win32.h b/include/fast_io_hosted/platforms/win32.h index a083062f..8ba9935c 100644 --- a/include/fast_io_hosted/platforms/win32.h +++ b/include/fast_io_hosted/platforms/win32.h @@ -1041,17 +1041,63 @@ class basic_win32_family_file : public basic_win32_family_io_observer inline void truncate(basic_win32_family_io_observer handle,::fast_io::uintfpos_t size) { - io_stream_seek_bytes_define(handle,size,seekdir::beg); + win32::details::seek_impl(handle, size, seekdir::beg); if(!::fast_io::win32::SetEndOfFile(handle.handle)) throw_win32_error(); } -#endif + namespace win32::details { +struct handle_guard +{ + void *h{}; + constexpr handle_guard() noexcept = default; + constexpr handle_guard(void *r) noexcept + : h{r} {}; + constexpr ~handle_guard() + { + if (h) [[likely]] + { + ::fast_io::win32::CloseHandle(h); + h = nullptr; + } + }; + constexpr void clear() noexcept + { + if (h) [[likely]] + { + ::fast_io::win32::CloseHandle(h); + h = nullptr; + } + } +}; + +struct map_guard +{ + void *map{}; + constexpr map_guard() noexcept = default; + constexpr map_guard(void *r) noexcept + : map{r} {}; + constexpr ~map_guard() + { + if (map) [[likely]] + { + ::fast_io::win32::UnmapViewOfFile(map); + map = nullptr; + } + }; + constexpr void clear() noexcept + { + if (map) [[likely]] + { + ::fast_io::win32::UnmapViewOfFile(map); + map = nullptr; + } + } +}; inline file_type file_type_impl(void *handle) { diff --git a/include/fast_io_hosted/process/win32.h b/include/fast_io_hosted/process/win32.h index df2f3f74..74927cbf 100644 --- a/include/fast_io_hosted/process/win32.h +++ b/include/fast_io_hosted/process/win32.h @@ -105,54 +105,6 @@ inline void win32_duplicate_object_std(void *parent_process, void *&standard_io_ template using win32_process_char_type = ::std::conditional_t; -struct map_guard -{ - void *map{}; - constexpr map_guard() noexcept = default; - constexpr map_guard(void *r) noexcept - : map{r} {}; - constexpr ~map_guard() - { - if (map) [[likely]] - { - ::fast_io::win32::UnmapViewOfFile(map); - map = nullptr; - } - }; - constexpr void clear() noexcept - { - if (map) [[likely]] - { - ::fast_io::win32::UnmapViewOfFile(map); - map = nullptr; - } - } -}; - -struct handle_guard -{ - void *h{}; - constexpr handle_guard() noexcept = default; - constexpr handle_guard(void *r) noexcept - : h{r} {}; - constexpr ~handle_guard() - { - if (h) [[likely]] - { - ::fast_io::win32::CloseHandle(h); - h = nullptr; - } - }; - constexpr void clear() noexcept - { - if (h) [[likely]] - { - ::fast_io::win32::CloseHandle(h); - h = nullptr; - } - } -}; - template inline win32_user_process_information win32_process_create_impl(void *__restrict fhandle, win32_process_char_type const *args, win32_process_char_type const *envs,