mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-25 14:50:26 +00:00
[libcxx] Fix the preexisting directory_iterator code for windows
The directory_iterator.cpp file did contain an incomplete, non-working implementation for windows. Change it to use the wchar version of the APIs. Don't set the windows specific errors from GetLastError() as code in the generic category; remap the errors to the std::errc values. Error out cleanly on empty paths. Invoke FindFirstFile on <directoryname>/* to actually list the entries of the directory. If the first entry retured by FindFirstFile is to be skipped (e.g. being "." or ".."), call advance() (which calls FindNextFile and loops) which doesn't return until a valid entry is found (or the end is reached). Differential Revision: https://reviews.llvm.org/D91140
This commit is contained in:
parent
de698ae734
commit
156180727d
@ -10,6 +10,7 @@
|
||||
#include "__config"
|
||||
#if defined(_LIBCPP_WIN32API)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <dirent.h>
|
||||
@ -72,16 +73,20 @@ static pair<string_view, file_type> posix_readdir(DIR* dir_stream,
|
||||
}
|
||||
}
|
||||
#else
|
||||
// defined(_LIBCPP_WIN32API)
|
||||
|
||||
static file_type get_file_type(const WIN32_FIND_DATA& data) {
|
||||
//auto attrs = data.dwFileAttributes;
|
||||
// FIXME(EricWF)
|
||||
return file_type::unknown;
|
||||
static file_type get_file_type(const WIN32_FIND_DATAW& data) {
|
||||
if (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT &&
|
||||
data.dwReserved0 == IO_REPARSE_TAG_SYMLINK)
|
||||
return file_type::symlink;
|
||||
if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
return file_type::directory;
|
||||
return file_type::regular;
|
||||
}
|
||||
static uintmax_t get_file_size(const WIN32_FIND_DATA& data) {
|
||||
return (data.nFileSizeHigh * (MAXDWORD + 1)) + data.nFileSizeLow;
|
||||
static uintmax_t get_file_size(const WIN32_FIND_DATAW& data) {
|
||||
return (static_cast<uint64_t>(data.nFileSizeHigh) << 32) + data.nFileSizeLow;
|
||||
}
|
||||
static file_time_type get_write_time(const WIN32_FIND_DATA& data) {
|
||||
static file_time_type get_write_time(const WIN32_FIND_DATAW& data) {
|
||||
ULARGE_INTEGER tmp;
|
||||
const FILETIME& time = data.ftLastWriteTime;
|
||||
tmp.u.LowPart = time.dwLowDateTime;
|
||||
@ -110,15 +115,21 @@ public:
|
||||
|
||||
__dir_stream(const path& root, directory_options opts, error_code& ec)
|
||||
: __stream_(INVALID_HANDLE_VALUE), __root_(root) {
|
||||
__stream_ = ::FindFirstFile(root.c_str(), &__data_);
|
||||
if (root.native().empty()) {
|
||||
ec = make_error_code(errc::no_such_file_or_directory);
|
||||
return;
|
||||
}
|
||||
__stream_ = ::FindFirstFileW((root / "*").c_str(), &__data_);
|
||||
if (__stream_ == INVALID_HANDLE_VALUE) {
|
||||
ec = error_code(::GetLastError(), generic_category());
|
||||
ec = detail::make_windows_error(GetLastError());
|
||||
const bool ignore_permission_denied =
|
||||
bool(opts & directory_options::skip_permission_denied);
|
||||
if (ignore_permission_denied && ec.value() == ERROR_ACCESS_DENIED)
|
||||
ec.clear();
|
||||
return;
|
||||
}
|
||||
if (!assign())
|
||||
advance(ec);
|
||||
}
|
||||
|
||||
~__dir_stream() noexcept {
|
||||
@ -130,35 +141,39 @@ public:
|
||||
bool good() const noexcept { return __stream_ != INVALID_HANDLE_VALUE; }
|
||||
|
||||
bool advance(error_code& ec) {
|
||||
while (::FindNextFile(__stream_, &__data_)) {
|
||||
if (!strcmp(__data_.cFileName, ".") || strcmp(__data_.cFileName, ".."))
|
||||
continue;
|
||||
// FIXME: Cache more of this
|
||||
//directory_entry::__cached_data cdata;
|
||||
//cdata.__type_ = get_file_type(__data_);
|
||||
//cdata.__size_ = get_file_size(__data_);
|
||||
//cdata.__write_time_ = get_write_time(__data_);
|
||||
__entry_.__assign_iter_entry(
|
||||
__root_ / __data_.cFileName,
|
||||
directory_entry::__create_iter_result(detail::get_file_type(__data)));
|
||||
return true;
|
||||
while (::FindNextFileW(__stream_, &__data_)) {
|
||||
if (assign())
|
||||
return true;
|
||||
}
|
||||
ec = error_code(::GetLastError(), generic_category());
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool assign() {
|
||||
if (!wcscmp(__data_.cFileName, L".") || !wcscmp(__data_.cFileName, L".."))
|
||||
return false;
|
||||
// FIXME: Cache more of this
|
||||
//directory_entry::__cached_data cdata;
|
||||
//cdata.__type_ = get_file_type(__data_);
|
||||
//cdata.__size_ = get_file_size(__data_);
|
||||
//cdata.__write_time_ = get_write_time(__data_);
|
||||
__entry_.__assign_iter_entry(
|
||||
__root_ / __data_.cFileName,
|
||||
directory_entry::__create_iter_result(detail::get_file_type(__data_)));
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
error_code close() noexcept {
|
||||
error_code ec;
|
||||
if (!::FindClose(__stream_))
|
||||
ec = error_code(::GetLastError(), generic_category());
|
||||
ec = detail::make_windows_error(GetLastError());
|
||||
__stream_ = INVALID_HANDLE_VALUE;
|
||||
return ec;
|
||||
}
|
||||
|
||||
HANDLE __stream_{INVALID_HANDLE_VALUE};
|
||||
WIN32_FIND_DATA __data_;
|
||||
WIN32_FIND_DATAW __data_;
|
||||
|
||||
public:
|
||||
path __root_;
|
||||
|
@ -17,11 +17,13 @@
|
||||
#include "cstdlib"
|
||||
#include "ctime"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/time.h> // for ::utimes as used in __last_write_time
|
||||
#include <fcntl.h> /* values for fchmodat */
|
||||
#if !defined(_LIBCPP_WIN32API)
|
||||
# include <unistd.h>
|
||||
# include <sys/stat.h>
|
||||
# include <sys/statvfs.h>
|
||||
# include <sys/time.h> // for ::utimes as used in __last_write_time
|
||||
# include <fcntl.h> /* values for fchmodat */
|
||||
#endif
|
||||
|
||||
#include "../include/apple_availability.h"
|
||||
|
||||
@ -47,6 +49,12 @@
|
||||
_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
|
||||
|
||||
namespace detail {
|
||||
|
||||
#if defined(_LIBCPP_WIN32API)
|
||||
// Non anonymous, to allow access from two translation units.
|
||||
errc __win_err_to_errc(int err);
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
static string format_string_imp(const char* msg, ...) {
|
||||
@ -118,6 +126,12 @@ error_code capture_errno() {
|
||||
return error_code(errno, generic_category());
|
||||
}
|
||||
|
||||
#if defined(_LIBCPP_WIN32API)
|
||||
error_code make_windows_error(int err) {
|
||||
return make_error_code(__win_err_to_errc(err));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
T error_value();
|
||||
template <>
|
||||
|
@ -309,6 +309,73 @@ string_view_t createView(PosPtr S, PosPtr E) noexcept {
|
||||
|
||||
// POSIX HELPERS
|
||||
|
||||
#if defined(_LIBCPP_WIN32API)
|
||||
namespace detail {
|
||||
|
||||
errc __win_err_to_errc(int err) {
|
||||
constexpr struct {
|
||||
DWORD win;
|
||||
errc errc;
|
||||
} win_error_mapping[] = {
|
||||
{ERROR_ACCESS_DENIED, errc::permission_denied},
|
||||
{ERROR_ALREADY_EXISTS, errc::file_exists},
|
||||
{ERROR_BAD_NETPATH, errc::no_such_file_or_directory},
|
||||
{ERROR_BAD_UNIT, errc::no_such_device},
|
||||
{ERROR_BROKEN_PIPE, errc::broken_pipe},
|
||||
{ERROR_BUFFER_OVERFLOW, errc::filename_too_long},
|
||||
{ERROR_BUSY, errc::device_or_resource_busy},
|
||||
{ERROR_BUSY_DRIVE, errc::device_or_resource_busy},
|
||||
{ERROR_CANNOT_MAKE, errc::permission_denied},
|
||||
{ERROR_CANTOPEN, errc::io_error},
|
||||
{ERROR_CANTREAD, errc::io_error},
|
||||
{ERROR_CANTWRITE, errc::io_error},
|
||||
{ERROR_CURRENT_DIRECTORY, errc::permission_denied},
|
||||
{ERROR_DEV_NOT_EXIST, errc::no_such_device},
|
||||
{ERROR_DEVICE_IN_USE, errc::device_or_resource_busy},
|
||||
{ERROR_DIR_NOT_EMPTY, errc::directory_not_empty},
|
||||
{ERROR_DIRECTORY, errc::invalid_argument},
|
||||
{ERROR_DISK_FULL, errc::no_space_on_device},
|
||||
{ERROR_FILE_EXISTS, errc::file_exists},
|
||||
{ERROR_FILE_NOT_FOUND, errc::no_such_file_or_directory},
|
||||
{ERROR_HANDLE_DISK_FULL, errc::no_space_on_device},
|
||||
{ERROR_INVALID_ACCESS, errc::permission_denied},
|
||||
{ERROR_INVALID_DRIVE, errc::no_such_device},
|
||||
{ERROR_INVALID_FUNCTION, errc::function_not_supported},
|
||||
{ERROR_INVALID_HANDLE, errc::invalid_argument},
|
||||
{ERROR_INVALID_NAME, errc::no_such_file_or_directory},
|
||||
{ERROR_INVALID_PARAMETER, errc::invalid_argument},
|
||||
{ERROR_LOCK_VIOLATION, errc::no_lock_available},
|
||||
{ERROR_LOCKED, errc::no_lock_available},
|
||||
{ERROR_NEGATIVE_SEEK, errc::invalid_argument},
|
||||
{ERROR_NOACCESS, errc::permission_denied},
|
||||
{ERROR_NOT_ENOUGH_MEMORY, errc::not_enough_memory},
|
||||
{ERROR_NOT_READY, errc::resource_unavailable_try_again},
|
||||
{ERROR_NOT_SAME_DEVICE, errc::cross_device_link},
|
||||
{ERROR_NOT_SUPPORTED, errc::not_supported},
|
||||
{ERROR_OPEN_FAILED, errc::io_error},
|
||||
{ERROR_OPEN_FILES, errc::device_or_resource_busy},
|
||||
{ERROR_OPERATION_ABORTED, errc::operation_canceled},
|
||||
{ERROR_OUTOFMEMORY, errc::not_enough_memory},
|
||||
{ERROR_PATH_NOT_FOUND, errc::no_such_file_or_directory},
|
||||
{ERROR_READ_FAULT, errc::io_error},
|
||||
{ERROR_REPARSE_TAG_INVALID, errc::invalid_argument},
|
||||
{ERROR_RETRY, errc::resource_unavailable_try_again},
|
||||
{ERROR_SEEK, errc::io_error},
|
||||
{ERROR_SHARING_VIOLATION, errc::permission_denied},
|
||||
{ERROR_TOO_MANY_OPEN_FILES, errc::too_many_files_open},
|
||||
{ERROR_WRITE_FAULT, errc::io_error},
|
||||
{ERROR_WRITE_PROTECT, errc::permission_denied},
|
||||
};
|
||||
|
||||
for (const auto &pair : win_error_mapping)
|
||||
if (pair.win == static_cast<DWORD>(err))
|
||||
return pair.errc;
|
||||
return errc::invalid_argument;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
namespace {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user