refactor
This commit is contained in:
parent
d07e1f9cce
commit
c22c68ef28
@ -75,8 +75,14 @@ private:
|
||||
std::unique_ptr<remote_winfsp::remote_server> remote_server_;
|
||||
|
||||
private:
|
||||
static auto
|
||||
parse_mount_location(const std::wstring &mount_location) -> std::string;
|
||||
[[nodiscard]] auto handle_error(std::string_view function_name,
|
||||
const std::string &api_path, api_error error,
|
||||
FileInfo *file_info, std::uint64_t file_size,
|
||||
bool raise_on_failure_only = false) const
|
||||
-> NTSTATUS;
|
||||
|
||||
static auto parse_mount_location(const std::wstring &mount_location)
|
||||
-> std::string;
|
||||
|
||||
void populate_file_info(const std::string &api_path, std::uint64_t file_size,
|
||||
const api_meta_map &meta,
|
||||
@ -89,8 +95,8 @@ private:
|
||||
const FSP_FSCTL_FILE_INFO &src);
|
||||
|
||||
public:
|
||||
auto CanDelete(PVOID file_node, PVOID file_desc,
|
||||
PWSTR file_name) -> NTSTATUS override;
|
||||
auto CanDelete(PVOID file_node, PVOID file_desc, PWSTR file_name)
|
||||
-> NTSTATUS override;
|
||||
|
||||
VOID Cleanup(PVOID file_node, PVOID file_desc, PWSTR file_name,
|
||||
ULONG flags) override;
|
||||
@ -102,8 +108,8 @@ public:
|
||||
UINT64 allocation_size, PVOID *file_node, PVOID *file_desc,
|
||||
OpenFileInfo *ofi) -> NTSTATUS override;
|
||||
|
||||
auto Flush(PVOID file_node, PVOID file_desc,
|
||||
FileInfo *file_info) -> NTSTATUS override;
|
||||
auto Flush(PVOID file_node, PVOID file_desc, FileInfo *file_info)
|
||||
-> NTSTATUS override;
|
||||
|
||||
[[nodiscard]] auto get_directory_item_count(const std::string &api_path) const
|
||||
-> std::uint64_t override;
|
||||
@ -111,24 +117,25 @@ public:
|
||||
[[nodiscard]] auto get_directory_items(const std::string &api_path) const
|
||||
-> directory_item_list override;
|
||||
|
||||
auto GetFileInfo(PVOID file_node, PVOID file_desc,
|
||||
FileInfo *file_info) -> NTSTATUS override;
|
||||
auto GetFileInfo(PVOID file_node, PVOID file_desc, FileInfo *file_info)
|
||||
-> NTSTATUS override;
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_file_size(const std::string &api_path) const -> std::uint64_t override;
|
||||
[[nodiscard]] auto get_file_size(const std::string &api_path) const
|
||||
-> std::uint64_t override;
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_item_meta(const std::string &api_path,
|
||||
api_meta_map &meta) const -> api_error override;
|
||||
[[nodiscard]] auto get_item_meta(const std::string &api_path,
|
||||
api_meta_map &meta) const
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_item_meta(const std::string &api_path, const std::string &name,
|
||||
std::string &value) const -> api_error override;
|
||||
[[nodiscard]] auto get_item_meta(const std::string &api_path,
|
||||
const std::string &name,
|
||||
std::string &value) const
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_security_by_name(PWSTR file_name, PUINT32 attributes,
|
||||
PSECURITY_DESCRIPTOR descriptor,
|
||||
std::uint64_t *descriptor_size) -> NTSTATUS override;
|
||||
[[nodiscard]] auto get_security_by_name(PWSTR file_name, PUINT32 attributes,
|
||||
PSECURITY_DESCRIPTOR descriptor,
|
||||
std::uint64_t *descriptor_size)
|
||||
-> NTSTATUS override;
|
||||
|
||||
auto GetSecurityByName(PWSTR file_name, PUINT32 attributes,
|
||||
PSECURITY_DESCRIPTOR descriptor,
|
||||
@ -152,16 +159,16 @@ public:
|
||||
auto Mounted(PVOID host) -> NTSTATUS override;
|
||||
|
||||
auto Open(PWSTR file_name, UINT32 create_options, UINT32 granted_access,
|
||||
PVOID *file_node, PVOID *file_desc,
|
||||
OpenFileInfo *ofi) -> NTSTATUS override;
|
||||
PVOID *file_node, PVOID *file_desc, OpenFileInfo *ofi)
|
||||
-> NTSTATUS override;
|
||||
|
||||
auto Overwrite(PVOID file_node, PVOID file_desc, UINT32 attributes,
|
||||
BOOLEAN replace_attributes, UINT64 allocation_size,
|
||||
FileInfo *file_info) -> NTSTATUS override;
|
||||
|
||||
[[nodiscard]] auto
|
||||
populate_file_info(const std::string &api_path,
|
||||
remote::file_info &file_info) -> api_error override;
|
||||
[[nodiscard]] auto populate_file_info(const std::string &api_path,
|
||||
remote::file_info &file_info)
|
||||
-> api_error override;
|
||||
|
||||
auto Read(PVOID file_node, PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||
ULONG length, PULONG bytes_transferred) -> NTSTATUS override;
|
||||
@ -171,8 +178,8 @@ public:
|
||||
PULONG bytes_transferred) -> NTSTATUS override;
|
||||
|
||||
auto Rename(PVOID file_node, PVOID file_desc, PWSTR file_name,
|
||||
PWSTR new_file_name,
|
||||
BOOLEAN replace_if_exists) -> NTSTATUS override;
|
||||
PWSTR new_file_name, BOOLEAN replace_if_exists)
|
||||
-> NTSTATUS override;
|
||||
|
||||
auto SetBasicInfo(PVOID file_node, PVOID file_desc, UINT32 attributes,
|
||||
UINT64 creation_time, UINT64 last_access_time,
|
||||
@ -180,15 +187,15 @@ public:
|
||||
FileInfo *file_info) -> NTSTATUS override;
|
||||
|
||||
auto SetFileSize(PVOID file_node, PVOID file_desc, UINT64 new_size,
|
||||
BOOLEAN set_allocation_size,
|
||||
FileInfo *file_info) -> NTSTATUS override;
|
||||
BOOLEAN set_allocation_size, FileInfo *file_info)
|
||||
-> NTSTATUS override;
|
||||
|
||||
VOID Unmounted(PVOID host) override;
|
||||
|
||||
auto Write(PVOID file_node, PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||
ULONG length, BOOLEAN write_to_end, BOOLEAN constrained_io,
|
||||
PULONG bytes_transferred,
|
||||
FileInfo *file_info) -> NTSTATUS override;
|
||||
PULONG bytes_transferred, FileInfo *file_info)
|
||||
-> NTSTATUS override;
|
||||
|
||||
void shutdown();
|
||||
|
||||
|
@ -67,13 +67,35 @@ winfsp_drive::winfsp_service::winfsp_service(
|
||||
host_(drive),
|
||||
config_(config) {}
|
||||
|
||||
auto winfsp_drive::handle_error(std::string_view function_name,
|
||||
const std::string &api_path, api_error error,
|
||||
FileInfo *file_info, std::uint64_t file_size,
|
||||
bool raise_on_failure_only) const -> NTSTATUS {
|
||||
auto ret = utils::from_api_error(error);
|
||||
if (not raise_on_failure_only || error != api_error::success) {
|
||||
RAISE_WINFSP_EVENT(function_name, api_path, ret);
|
||||
}
|
||||
|
||||
if (file_info == nullptr || error != api_error::success) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
api_meta_map meta;
|
||||
if (provider_.get_item_meta(api_path, meta) != api_error::success) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
populate_file_info(file_size, meta, *file_info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto winfsp_drive::winfsp_service::OnStart(ULONG /*Argc*/, PWSTR * /*Argv*/)
|
||||
-> NTSTATUS {
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
||||
const auto mount_location = utils::string::to_lower(
|
||||
auto mount_location = utils::string::to_lower(
|
||||
utils::path::absolute((drive_args_.size() > 1U) ? drive_args_[1U] : ""));
|
||||
const auto drive_letter =
|
||||
auto drive_letter =
|
||||
((mount_location.size() == 2U) ||
|
||||
((mount_location.size() == 3U) && (mount_location[2U] == '\\'))) &&
|
||||
(mount_location[1U] == ':');
|
||||
@ -132,27 +154,26 @@ auto winfsp_drive::CanDelete(PVOID /*file_node*/, PVOID file_desc,
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
||||
std::string api_path;
|
||||
auto error = api_error::invalid_handle;
|
||||
std::shared_ptr<i_open_file> file;
|
||||
const auto handle_error = [this, &api_path](api_error error) -> NTSTATUS {
|
||||
return this->handle_error(function_name, api_path, error, nullptr, 0U);
|
||||
};
|
||||
|
||||
auto handle =
|
||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
||||
if (handle != 0U) {
|
||||
std::shared_ptr<i_open_file> file;
|
||||
if (fm_->get_open_file(handle, false, file)) {
|
||||
api_path = file->get_api_path();
|
||||
if (file->is_directory()) {
|
||||
error = provider_.get_directory_item_count(api_path) != 0U
|
||||
? api_error::directory_not_empty
|
||||
: api_error::success;
|
||||
} else {
|
||||
error = fm_->is_processing(api_path) ? api_error::file_in_use
|
||||
: api_error::success;
|
||||
}
|
||||
}
|
||||
if (handle == 0U || not fm_->get_open_file(handle, false, file)) {
|
||||
return handle_error(api_error::invalid_handle);
|
||||
}
|
||||
|
||||
auto ret = utils::from_api_error(error);
|
||||
RAISE_WINFSP_EVENT(function_name, api_path, ret);
|
||||
return ret;
|
||||
api_path = file->get_api_path();
|
||||
if (file->is_directory()) {
|
||||
return handle_error(provider_.get_directory_item_count(api_path) == 0U
|
||||
? api_error::success
|
||||
: api_error::directory_not_empty);
|
||||
}
|
||||
|
||||
return handle_error(fm_->is_processing(api_path) ? api_error::file_in_use
|
||||
: api_error::success);
|
||||
}
|
||||
|
||||
VOID winfsp_drive::Cleanup(PVOID file_node, PVOID file_desc,
|
||||
@ -160,130 +181,126 @@ VOID winfsp_drive::Cleanup(PVOID file_node, PVOID file_desc,
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
||||
std::string api_path;
|
||||
std::shared_ptr<i_open_file> file;
|
||||
const auto handle_error = [this, &api_path](api_error error) {
|
||||
[[maybe_unused]] auto ret =
|
||||
this->handle_error(function_name, api_path, error, nullptr, 0U);
|
||||
};
|
||||
|
||||
auto handle =
|
||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
||||
if (handle != 0U) {
|
||||
std::shared_ptr<i_open_file> file;
|
||||
if (fm_->get_open_file(handle, false, file)) {
|
||||
api_path = file->get_api_path();
|
||||
if (handle == 0U || not fm_->get_open_file(handle, false, file)) {
|
||||
return handle_error(api_error::invalid_handle);
|
||||
}
|
||||
|
||||
const auto directory = file->is_directory();
|
||||
if ((flags & FspCleanupDelete) != 0U) {
|
||||
auto *directory_buffer = file->get_open_data(handle).directory_buffer;
|
||||
file.reset();
|
||||
api_path = file->get_api_path();
|
||||
|
||||
if (directory_buffer != nullptr) {
|
||||
FspFileSystemDeleteDirectoryBuffer(&directory_buffer);
|
||||
}
|
||||
auto directory = file->is_directory();
|
||||
if ((flags & FspCleanupDelete) != 0U) {
|
||||
auto *directory_buffer = file->get_open_data(handle).directory_buffer;
|
||||
file.reset();
|
||||
|
||||
if (directory) {
|
||||
if (provider_.get_directory_item_count(api_path) == 0) {
|
||||
auto res = provider_.remove_directory(api_path);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(function_name, api_path, res,
|
||||
"failed to remove directory");
|
||||
}
|
||||
} else {
|
||||
utils::error::raise_api_path_error(
|
||||
function_name, api_path, api_error::directory_not_empty,
|
||||
"failed to remove non-empty directory");
|
||||
}
|
||||
} else {
|
||||
auto res = fm_->remove_file(api_path);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(function_name, api_path, res,
|
||||
"failed to remove file");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (((flags & FspCleanupSetArchiveBit) != 0U) && not directory) {
|
||||
api_meta_map meta;
|
||||
if (provider_.get_item_meta(api_path, meta) == api_error::success) {
|
||||
auto res = provider_.set_item_meta(
|
||||
api_path, META_ATTRIBUTES,
|
||||
std::to_string(utils::get_attributes_from_meta(meta) |
|
||||
FILE_ATTRIBUTE_ARCHIVE));
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(
|
||||
function_name, api_path, res,
|
||||
"failed to set meta attributes");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (directory_buffer != nullptr) {
|
||||
FspFileSystemDeleteDirectoryBuffer(&directory_buffer);
|
||||
}
|
||||
|
||||
if ((flags & (FspCleanupSetLastAccessTime | FspCleanupSetLastWriteTime |
|
||||
FspCleanupSetChangeTime)) != 0U) {
|
||||
const auto now = utils::time::get_time_now();
|
||||
if ((flags & FspCleanupSetLastAccessTime) != 0U) {
|
||||
auto res = provider_.set_item_meta(api_path, META_ACCESSED,
|
||||
std::to_string(now));
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(
|
||||
function_name, api_path, res,
|
||||
"failed to set meta accessed time");
|
||||
}
|
||||
}
|
||||
if (directory) {
|
||||
if (provider_.get_directory_item_count(api_path) == 0) {
|
||||
return handle_error(provider_.remove_directory(api_path));
|
||||
}
|
||||
|
||||
if ((flags & FspCleanupSetLastWriteTime) != 0U) {
|
||||
auto res = provider_.set_item_meta(api_path, META_WRITTEN,
|
||||
std::to_string(now));
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(
|
||||
function_name, api_path, res,
|
||||
"failed to set meta written time");
|
||||
}
|
||||
}
|
||||
return handle_error(api_error::directory_not_empty);
|
||||
}
|
||||
|
||||
if ((flags & FspCleanupSetChangeTime) != 0U) {
|
||||
auto res = provider_.set_item_meta(
|
||||
api_path, {
|
||||
{META_CHANGED, std::to_string(now)},
|
||||
{META_MODIFIED, std::to_string(now)},
|
||||
});
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(
|
||||
function_name, api_path, res,
|
||||
"failed to set meta modified time");
|
||||
}
|
||||
}
|
||||
}
|
||||
return handle_error(fm_->remove_file(api_path));
|
||||
}
|
||||
|
||||
if ((flags & FspCleanupSetAllocationSize) != 0U) {
|
||||
auto allocation_size =
|
||||
utils::divide_with_ceiling(file->get_file_size(),
|
||||
WINFSP_ALLOCATION_UNIT) *
|
||||
WINFSP_ALLOCATION_UNIT;
|
||||
SetFileSize(file_node, file_desc, allocation_size, TRUE, nullptr);
|
||||
}
|
||||
if (((flags & FspCleanupSetArchiveBit) != 0U) && not directory) {
|
||||
api_meta_map meta;
|
||||
if (provider_.get_item_meta(api_path, meta) == api_error::success) {
|
||||
auto res = provider_.set_item_meta(
|
||||
api_path, META_ATTRIBUTES,
|
||||
std::to_string(utils::get_attributes_from_meta(meta) |
|
||||
FILE_ATTRIBUTE_ARCHIVE));
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(function_name, api_path, res,
|
||||
"failed to set meta attributes");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RAISE_WINFSP_EVENT(function_name, api_path, 0);
|
||||
if ((flags & (FspCleanupSetLastAccessTime | FspCleanupSetLastWriteTime |
|
||||
FspCleanupSetChangeTime)) != 0U) {
|
||||
auto now = utils::time::get_time_now();
|
||||
if ((flags & FspCleanupSetLastAccessTime) != 0U) {
|
||||
auto res =
|
||||
provider_.set_item_meta(api_path, META_ACCESSED, std::to_string(now));
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(function_name, api_path, res,
|
||||
"failed to set meta accessed time");
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & FspCleanupSetLastWriteTime) != 0U) {
|
||||
auto res =
|
||||
provider_.set_item_meta(api_path, META_WRITTEN, std::to_string(now));
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(function_name, api_path, res,
|
||||
"failed to set meta written time");
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & FspCleanupSetChangeTime) != 0U) {
|
||||
auto res = provider_.set_item_meta(
|
||||
api_path, {
|
||||
{META_CHANGED, std::to_string(now)},
|
||||
{META_MODIFIED, std::to_string(now)},
|
||||
});
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(function_name, api_path, res,
|
||||
"failed to set meta modified time");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & FspCleanupSetAllocationSize) != 0U) {
|
||||
auto allocation_size = utils::divide_with_ceiling(file->get_file_size(),
|
||||
WINFSP_ALLOCATION_UNIT) *
|
||||
WINFSP_ALLOCATION_UNIT;
|
||||
SetFileSize(file_node, file_desc, allocation_size, TRUE, nullptr);
|
||||
}
|
||||
|
||||
return handle_error(api_error::success);
|
||||
}
|
||||
|
||||
VOID winfsp_drive::Close(PVOID /*file_node*/, PVOID file_desc) {
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
||||
std::string api_path;
|
||||
std::shared_ptr<i_open_file> file;
|
||||
const auto handle_error = [this, &api_path](api_error error) {
|
||||
[[maybe_unused]] auto ret =
|
||||
this->handle_error(function_name, api_path, error, nullptr, 0U);
|
||||
};
|
||||
|
||||
auto handle =
|
||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
||||
if (handle != 0U) {
|
||||
PVOID directory_buffer{nullptr};
|
||||
|
||||
std::shared_ptr<i_open_file> file;
|
||||
if (fm_->get_open_file(handle, false, file)) {
|
||||
api_path = file->get_api_path();
|
||||
directory_buffer = file->get_open_data(handle).directory_buffer;
|
||||
file.reset();
|
||||
}
|
||||
fm_->close(handle);
|
||||
if (directory_buffer != nullptr) {
|
||||
FspFileSystemDeleteDirectoryBuffer(&directory_buffer);
|
||||
}
|
||||
if (handle == 0U || not fm_->get_open_file(handle, false, file)) {
|
||||
return handle_error(api_error::invalid_handle);
|
||||
}
|
||||
|
||||
RAISE_WINFSP_EVENT(function_name, api_path, 0);
|
||||
PVOID directory_buffer{nullptr};
|
||||
|
||||
api_path = file->get_api_path();
|
||||
directory_buffer = file->get_open_data(handle).directory_buffer;
|
||||
file.reset();
|
||||
fm_->close(handle);
|
||||
|
||||
if (directory_buffer != nullptr) {
|
||||
FspFileSystemDeleteDirectoryBuffer(&directory_buffer);
|
||||
}
|
||||
|
||||
return handle_error(api_error::success);
|
||||
}
|
||||
|
||||
auto winfsp_drive::Create(PWSTR file_name, UINT32 create_options,
|
||||
@ -306,7 +323,7 @@ auto winfsp_drive::Create(PWSTR file_name, UINT32 create_options,
|
||||
attributes |= FILE_ATTRIBUTE_ARCHIVE;
|
||||
}
|
||||
|
||||
const auto now = utils::time::get_time_now();
|
||||
auto now = utils::time::get_time_now();
|
||||
auto meta = create_meta_attributes(
|
||||
now, attributes, now, now, (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0U,
|
||||
0U, "", 0U, now, 0U, 0U, 0U,
|
||||
@ -316,7 +333,7 @@ auto winfsp_drive::Create(PWSTR file_name, UINT32 create_options,
|
||||
{utils::create_uuid_string()}),
|
||||
0U, now);
|
||||
|
||||
const auto api_path =
|
||||
auto api_path =
|
||||
utils::path::create_api_path(utils::string::to_utf8(file_name));
|
||||
|
||||
open_file_data ofd{};
|
||||
@ -350,33 +367,27 @@ auto winfsp_drive::Flush(PVOID /*file_node*/, PVOID file_desc,
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
||||
std::string api_path;
|
||||
auto error = api_error::success;
|
||||
std::shared_ptr<i_open_file> file;
|
||||
const auto handle_error = [this, &api_path, &file,
|
||||
&file_info](api_error error) -> NTSTATUS {
|
||||
return this->handle_error(function_name, api_path, error, file_info,
|
||||
file ? file->get_file_size() : 0U);
|
||||
};
|
||||
|
||||
auto handle =
|
||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
||||
if (handle != 0U) {
|
||||
error = api_error::invalid_handle;
|
||||
std::shared_ptr<i_open_file> file;
|
||||
if (fm_->get_open_file(handle, false, file)) {
|
||||
api_path = file->get_api_path();
|
||||
error = file->native_operation([&](native_handle op_handle) {
|
||||
if (::FlushFileBuffers(op_handle) == 0) {
|
||||
return api_error::os_error;
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
});
|
||||
|
||||
// Populate file information
|
||||
api_meta_map meta;
|
||||
if (provider_.get_item_meta(api_path, meta) == api_error::success) {
|
||||
populate_file_info(file->get_file_size(), meta, *file_info);
|
||||
}
|
||||
}
|
||||
if (handle == 0U || not fm_->get_open_file(handle, false, file)) {
|
||||
return handle_error(api_error::invalid_handle);
|
||||
}
|
||||
|
||||
auto ret = utils::from_api_error(error);
|
||||
RAISE_WINFSP_EVENT(function_name, api_path, ret);
|
||||
return ret;
|
||||
api_path = file->get_api_path();
|
||||
return handle_error(file->native_operation([&](native_handle op_handle) {
|
||||
if (::FlushFileBuffers(op_handle) == 0) {
|
||||
return api_error::os_error;
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
}));
|
||||
}
|
||||
|
||||
auto winfsp_drive::get_directory_item_count(const std::string &api_path) const
|
||||
@ -402,24 +413,20 @@ auto winfsp_drive::GetFileInfo(PVOID /*file_node*/, PVOID file_desc,
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
||||
std::string api_path;
|
||||
auto error = api_error::invalid_handle;
|
||||
std::shared_ptr<i_open_file> file;
|
||||
const auto handle_error = [this, &api_path, &file,
|
||||
&file_info](api_error error) -> NTSTATUS {
|
||||
return this->handle_error(function_name, api_path, error, file_info,
|
||||
file ? file->get_file_size() : 0U);
|
||||
};
|
||||
|
||||
auto handle =
|
||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
||||
if (handle != 0U) {
|
||||
std::shared_ptr<i_open_file> file;
|
||||
if (fm_->get_open_file(handle, false, file)) {
|
||||
api_path = file->get_api_path();
|
||||
api_meta_map meta;
|
||||
error = provider_.get_item_meta(api_path, meta);
|
||||
if (error == api_error::success) {
|
||||
populate_file_info(file->get_file_size(), meta, *file_info);
|
||||
}
|
||||
}
|
||||
if (handle == 0U || not fm_->get_open_file(handle, false, file)) {
|
||||
return handle_error(api_error::invalid_handle);
|
||||
}
|
||||
|
||||
auto ret = utils::from_api_error(error);
|
||||
RAISE_WINFSP_EVENT(function_name, api_path, ret);
|
||||
return ret;
|
||||
return handle_error(api_error::success);
|
||||
}
|
||||
|
||||
auto winfsp_drive::get_file_size(const std::string &api_path) const
|
||||
@ -457,7 +464,7 @@ auto winfsp_drive::get_security_by_name(PWSTR file_name, PUINT32 attributes,
|
||||
PSECURITY_DESCRIPTOR descriptor,
|
||||
std::uint64_t *descriptor_size)
|
||||
-> NTSTATUS {
|
||||
const auto api_path =
|
||||
auto api_path =
|
||||
utils::path::create_api_path(utils::string::to_utf8(file_name));
|
||||
|
||||
api_meta_map meta{};
|
||||
@ -494,7 +501,7 @@ auto winfsp_drive::GetSecurityByName(PWSTR file_name, PUINT32 attributes,
|
||||
SIZE_T *descriptor_size) -> NTSTATUS {
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
||||
const auto api_path =
|
||||
auto api_path =
|
||||
utils::path::create_api_path(utils::string::to_utf8(file_name));
|
||||
std::uint64_t sds = descriptor_size == nullptr ? 0U : *descriptor_size;
|
||||
auto ret = get_security_by_name(file_name, attributes, descriptor,
|
||||
@ -521,8 +528,8 @@ auto winfsp_drive::get_used_drive_space() const -> std::uint64_t {
|
||||
|
||||
void winfsp_drive::get_volume_info(UINT64 &total_size, UINT64 &free_size,
|
||||
std::string &volume_label) const {
|
||||
const auto total_bytes = provider_.get_total_drive_space();
|
||||
const auto total_used = provider_.get_used_drive_space();
|
||||
auto total_bytes = provider_.get_total_drive_space();
|
||||
auto total_used = provider_.get_used_drive_space();
|
||||
free_size = total_bytes - total_used;
|
||||
total_size = total_bytes;
|
||||
volume_label = utils::create_volume_label(config_.get_provider_type());
|
||||
@ -533,8 +540,8 @@ auto winfsp_drive::GetVolumeInfo(VolumeInfo *volume_info) -> NTSTATUS {
|
||||
|
||||
const std::wstring volume_label = utils::string::from_utf8(
|
||||
utils::create_volume_label(config_.get_provider_type()));
|
||||
const auto total_bytes = provider_.get_total_drive_space();
|
||||
const auto total_used = provider_.get_used_drive_space();
|
||||
auto total_bytes = provider_.get_total_drive_space();
|
||||
auto total_used = provider_.get_used_drive_space();
|
||||
volume_info->FreeSize = total_bytes - total_used;
|
||||
volume_info->TotalSize = total_bytes;
|
||||
wcscpy_s(&volume_info->VolumeLabel[0U], 32, volume_label.data());
|
||||
@ -577,7 +584,7 @@ auto winfsp_drive::Init(PVOID host) -> NTSTATUS {
|
||||
auto winfsp_drive::mount(const std::vector<std::string> &drive_args) -> int {
|
||||
std::vector<std::string> parsed_drive_args;
|
||||
|
||||
const auto force_no_console = utils::collection::includes(drive_args, "-nc");
|
||||
auto force_no_console = utils::collection::includes(drive_args, "-nc");
|
||||
|
||||
auto enable_console = false;
|
||||
for (auto &&arg : drive_args) {
|
||||
@ -638,8 +645,7 @@ auto winfsp_drive::Mounted(PVOID host) -> NTSTATUS {
|
||||
eviction_->start();
|
||||
}
|
||||
|
||||
const auto mount_location =
|
||||
parse_mount_location(file_system_host->MountPoint());
|
||||
auto mount_location = parse_mount_location(file_system_host->MountPoint());
|
||||
if (config_.get_enable_remote_mount()) {
|
||||
remote_server_ = std::make_unique<remote_winfsp::remote_server>(
|
||||
config_, *this, mount_location);
|
||||
@ -675,7 +681,7 @@ auto winfsp_drive::Open(PWSTR file_name, UINT32 create_options,
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
*file_desc = reinterpret_cast<PVOID>(INVALID_HANDLE_VALUE);
|
||||
|
||||
const auto api_path =
|
||||
auto api_path =
|
||||
utils::path::create_api_path(utils::string::to_utf8(file_name));
|
||||
|
||||
bool directory{};
|
||||
@ -723,49 +729,58 @@ auto winfsp_drive::Overwrite(PVOID /*file_node*/, PVOID file_desc,
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
||||
std::string api_path;
|
||||
auto error = api_error::invalid_handle;
|
||||
std::shared_ptr<i_open_file> file;
|
||||
const auto handle_error = [this, &api_path, &file,
|
||||
&file_info](api_error error) -> NTSTATUS {
|
||||
return this->handle_error(function_name, api_path, error, file_info,
|
||||
file ? file->get_file_size() : 0U);
|
||||
};
|
||||
|
||||
auto handle =
|
||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
||||
if (handle != 0U) {
|
||||
std::shared_ptr<i_open_file> file;
|
||||
if (fm_->get_open_file(handle, true, file)) {
|
||||
api_path = file->get_api_path();
|
||||
api_meta_map meta{};
|
||||
error = provider_.get_item_meta(api_path, meta);
|
||||
if (error == api_error::success) {
|
||||
error = file->resize(0U);
|
||||
if (error == api_error::success) {
|
||||
filesystem_item existing_fsi{};
|
||||
error = provider_.get_filesystem_item(api_path, false, existing_fsi);
|
||||
if (error == api_error::success) {
|
||||
// Handle replace attributes
|
||||
if (replace_attributes != 0U) {
|
||||
if (attributes == 0U || attributes == FILE_ATTRIBUTE_NORMAL) {
|
||||
attributes = FILE_ATTRIBUTE_ARCHIVE;
|
||||
}
|
||||
meta[META_ATTRIBUTES] = std::to_string(attributes);
|
||||
error = provider_.set_item_meta(api_path, meta);
|
||||
} else if (attributes != 0U) { // Handle merge attributes
|
||||
const auto current_attributes =
|
||||
utils::get_attributes_from_meta(meta);
|
||||
const auto merged_attributes = attributes | current_attributes;
|
||||
if (merged_attributes != current_attributes) {
|
||||
meta[META_ATTRIBUTES] = std::to_string(merged_attributes);
|
||||
error = provider_.set_item_meta(api_path, meta);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Populate file information
|
||||
populate_file_info(file->get_file_size(), meta, *file_info);
|
||||
}
|
||||
}
|
||||
if (handle == 0U || not fm_->get_open_file(handle, true, file)) {
|
||||
return handle_error(api_error::invalid_handle);
|
||||
}
|
||||
|
||||
auto ret = utils::from_api_error(error);
|
||||
RAISE_WINFSP_EVENT(function_name, api_path, ret);
|
||||
return ret;
|
||||
api_path = file->get_api_path();
|
||||
api_meta_map meta{};
|
||||
auto res = provider_.get_item_meta(api_path, meta);
|
||||
if (res != api_error::success) {
|
||||
return handle_error(res);
|
||||
}
|
||||
|
||||
res = file->resize(0U);
|
||||
if (res != api_error::success) {
|
||||
return handle_error(res);
|
||||
}
|
||||
|
||||
filesystem_item existing_fsi{};
|
||||
res = provider_.get_filesystem_item(api_path, false, existing_fsi);
|
||||
if (res != api_error::success) {
|
||||
return handle_error(res);
|
||||
}
|
||||
|
||||
if (replace_attributes != 0U) {
|
||||
if (attributes == 0U || attributes == FILE_ATTRIBUTE_NORMAL) {
|
||||
attributes = FILE_ATTRIBUTE_ARCHIVE;
|
||||
}
|
||||
|
||||
meta[META_ATTRIBUTES] = std::to_string(attributes);
|
||||
return handle_error(provider_.set_item_meta(api_path, meta));
|
||||
}
|
||||
|
||||
if (attributes == 0U) {
|
||||
return handle_error(api_error::success);
|
||||
}
|
||||
|
||||
auto current_attributes = utils::get_attributes_from_meta(meta);
|
||||
auto merged_attributes = attributes | current_attributes;
|
||||
if (merged_attributes != current_attributes) {
|
||||
meta[META_ATTRIBUTES] = std::to_string(merged_attributes);
|
||||
return handle_error(provider_.set_item_meta(api_path, meta));
|
||||
}
|
||||
|
||||
return handle_error(api_error::success);
|
||||
}
|
||||
|
||||
auto winfsp_drive::parse_mount_location(const std::wstring &mount_location)
|
||||
@ -779,7 +794,7 @@ void winfsp_drive::populate_file_info(const std::string &api_path,
|
||||
std::uint64_t file_size,
|
||||
const api_meta_map &meta,
|
||||
FSP_FSCTL_OPEN_FILE_INFO &ofi) {
|
||||
const auto file_path = utils::string::from_utf8(
|
||||
auto file_path = utils::string::from_utf8(
|
||||
utils::string::replace_copy(api_path, '/', '\\'));
|
||||
|
||||
wcscpy_s(ofi.NormalizedName, ofi.NormalizedNameSize / sizeof(WCHAR),
|
||||
@ -829,47 +844,45 @@ auto winfsp_drive::Read(PVOID /*file_node*/, PVOID file_desc, PVOID buffer,
|
||||
*bytes_transferred = 0U;
|
||||
|
||||
std::string api_path;
|
||||
auto error = api_error::invalid_handle;
|
||||
std::shared_ptr<i_open_file> file;
|
||||
const auto handle_error = [this, &api_path](api_error error) -> NTSTATUS {
|
||||
return this->handle_error(function_name, api_path, error, nullptr, 0U);
|
||||
};
|
||||
|
||||
auto handle =
|
||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
||||
if (handle != 0U) {
|
||||
if (length > 0U) {
|
||||
std::shared_ptr<i_open_file> file;
|
||||
if (fm_->get_open_file(handle, false, file)) {
|
||||
api_path = file->get_api_path();
|
||||
data_buffer data;
|
||||
error = file->read(length, offset, data);
|
||||
if (error == api_error::success) {
|
||||
*bytes_transferred = static_cast<ULONG>(data.size());
|
||||
if ((length > 0) && (data.size() != length)) {
|
||||
::SetLastError(ERROR_HANDLE_EOF);
|
||||
}
|
||||
|
||||
if (not data.empty()) {
|
||||
::CopyMemory(buffer, data.data(), data.size());
|
||||
data.clear();
|
||||
auto res = provider_.set_item_meta(
|
||||
api_path, META_ACCESSED,
|
||||
std::to_string(utils::time::get_time_now()));
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(
|
||||
function_name, api_path, res,
|
||||
"failed to set meta accessed time");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error = api_error::success;
|
||||
}
|
||||
if (handle == 0U || not fm_->get_open_file(handle, false, file)) {
|
||||
return handle_error(api_error::invalid_handle);
|
||||
}
|
||||
|
||||
auto ret = utils::from_api_error(error);
|
||||
if (ret != STATUS_SUCCESS) {
|
||||
RAISE_WINFSP_EVENT(function_name, api_path, ret);
|
||||
api_path = file->get_api_path();
|
||||
|
||||
if (length == 0U) {
|
||||
return handle_error(api_error::success);
|
||||
}
|
||||
|
||||
return ret;
|
||||
data_buffer data;
|
||||
auto res = file->read(length, offset, data);
|
||||
if (res != api_error::success) {
|
||||
return handle_error(res);
|
||||
}
|
||||
|
||||
*bytes_transferred = static_cast<ULONG>(data.size());
|
||||
if ((length > 0) && (data.size() != length)) {
|
||||
::SetLastError(ERROR_HANDLE_EOF);
|
||||
}
|
||||
|
||||
if (data.empty()) {
|
||||
return handle_error(api_error::success);
|
||||
}
|
||||
|
||||
::CopyMemory(buffer, data.data(), data.size());
|
||||
data.clear();
|
||||
|
||||
return handle_error(
|
||||
provider_.set_item_meta(api_path, META_ACCESSED,
|
||||
std::to_string(utils::time::get_time_now())),
|
||||
true);
|
||||
}
|
||||
|
||||
auto winfsp_drive::ReadDirectory(PVOID /*file_node*/, PVOID file_desc,
|
||||
@ -920,7 +933,7 @@ auto winfsp_drive::ReadDirectory(PVOID /*file_node*/, PVOID file_desc,
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto display_name = utils::string::from_utf8(
|
||||
auto display_name = utils::string::from_utf8(
|
||||
utils::path::strip_to_file_name(dir_item.api_path));
|
||||
union {
|
||||
UINT8 B[FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) +
|
||||
@ -977,29 +990,41 @@ auto winfsp_drive::Rename(PVOID /*file_node*/, PVOID /*file_desc*/,
|
||||
BOOLEAN replace_if_exists) -> NTSTATUS {
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
||||
const auto from_api_path =
|
||||
std::string api_path;
|
||||
|
||||
auto from_api_path =
|
||||
utils::path::create_api_path(utils::string::to_utf8(file_name));
|
||||
const auto to_api_path =
|
||||
|
||||
auto to_api_path =
|
||||
utils::path::create_api_path(utils::string::to_utf8(new_file_name));
|
||||
|
||||
auto error = api_error::item_not_found;
|
||||
const auto handle_error = [this, &from_api_path,
|
||||
&to_api_path](api_error error) -> NTSTATUS {
|
||||
return this->handle_error(function_name, from_api_path + '|' + to_api_path,
|
||||
error, nullptr, 0U);
|
||||
};
|
||||
|
||||
bool exists{};
|
||||
error = provider_.is_file(from_api_path, exists);
|
||||
if (error == api_error::success) {
|
||||
if (exists) {
|
||||
error =
|
||||
fm_->rename_file(from_api_path, to_api_path, replace_if_exists != 0U);
|
||||
} else {
|
||||
error = provider_.is_directory(from_api_path, exists);
|
||||
if (error == api_error::success && exists) {
|
||||
error = fm_->rename_directory(from_api_path, to_api_path);
|
||||
}
|
||||
}
|
||||
auto res = provider_.is_file(from_api_path, exists);
|
||||
if res != api_error::success) {
|
||||
return handle_error(res);
|
||||
}
|
||||
|
||||
auto ret = utils::from_api_error(error);
|
||||
RAISE_WINFSP_EVENT(function_name, from_api_path + "|" + to_api_path, ret);
|
||||
return ret;
|
||||
if (exists) {
|
||||
return handle_error(
|
||||
fm_->rename_file(from_api_path, to_api_path, replace_if_exists != 0U));
|
||||
}
|
||||
|
||||
res = provider_.is_directory(from_api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return handle_error(res);
|
||||
}
|
||||
|
||||
if (exists) {
|
||||
return handle_error(fm_->rename_directory(from_api_path, to_api_path));
|
||||
}
|
||||
|
||||
return handle_error(api_error::item_not_found);
|
||||
}
|
||||
|
||||
auto winfsp_drive::SetBasicInfo(PVOID /*file_node*/, PVOID file_desc,
|
||||
@ -1010,61 +1035,60 @@ auto winfsp_drive::SetBasicInfo(PVOID /*file_node*/, PVOID file_desc,
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
||||
std::string api_path;
|
||||
auto error = api_error::invalid_handle;
|
||||
std::shared_ptr<i_open_file> file;
|
||||
const auto handle_error = [this, &api_path, &file,
|
||||
&file_info](api_error error) -> NTSTATUS {
|
||||
return this->handle_error(function_name, api_path, error, file_info,
|
||||
file ? file->get_file_size() : 0U);
|
||||
};
|
||||
|
||||
auto handle =
|
||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
||||
if (handle != 0U) {
|
||||
std::shared_ptr<i_open_file> file;
|
||||
if (fm_->get_open_file(handle, false, file)) {
|
||||
api_path = file->get_api_path();
|
||||
if (attributes == INVALID_FILE_ATTRIBUTES) {
|
||||
attributes = 0U;
|
||||
} else if (attributes == 0U) {
|
||||
attributes = file->is_directory() ? FILE_ATTRIBUTE_DIRECTORY
|
||||
: FILE_ATTRIBUTE_ARCHIVE;
|
||||
}
|
||||
|
||||
api_meta_map meta;
|
||||
if (attributes != 0U) {
|
||||
auto next_attributes =
|
||||
attributes & static_cast<UINT32>(~FILE_ATTRIBUTE_NORMAL);
|
||||
if (next_attributes == 0U) {
|
||||
next_attributes = attributes;
|
||||
}
|
||||
meta[META_ATTRIBUTES] = std::to_string(next_attributes);
|
||||
}
|
||||
if ((creation_time != 0U) && (creation_time != max_time)) {
|
||||
meta[META_CREATION] = std::to_string(
|
||||
utils::time::windows_time_to_unix_time(creation_time));
|
||||
}
|
||||
if ((last_access_time != 0U) && (last_access_time != max_time)) {
|
||||
meta[META_ACCESSED] = std::to_string(
|
||||
utils::time::windows_time_to_unix_time(last_access_time));
|
||||
}
|
||||
if ((last_write_time != 0U) && (last_write_time != max_time)) {
|
||||
meta[META_WRITTEN] = std::to_string(
|
||||
utils::time::windows_time_to_unix_time(last_write_time));
|
||||
}
|
||||
if ((change_time != 0U) && (change_time != max_time)) {
|
||||
meta[META_CHANGED] =
|
||||
std::to_string(utils::time::windows_time_to_unix_time(change_time));
|
||||
meta[META_MODIFIED] =
|
||||
std::to_string(utils::time::windows_time_to_unix_time(change_time));
|
||||
}
|
||||
|
||||
error = provider_.set_item_meta(api_path, meta);
|
||||
|
||||
// Populate file information
|
||||
if (provider_.get_item_meta(api_path, meta) == api_error::success) {
|
||||
populate_file_info(utils::string::to_uint64(meta[META_SIZE]), meta,
|
||||
*file_info);
|
||||
}
|
||||
}
|
||||
if (handle == 0U || not fm_->get_open_file(handle, true, file)) {
|
||||
return handle_error(api_error::invalid_handle);
|
||||
}
|
||||
|
||||
auto ret = utils::from_api_error(error);
|
||||
RAISE_WINFSP_EVENT(function_name, api_path, ret);
|
||||
return ret;
|
||||
api_path = file->get_api_path();
|
||||
if (attributes == INVALID_FILE_ATTRIBUTES) {
|
||||
attributes = 0U;
|
||||
} else if (attributes == 0U) {
|
||||
attributes = file->is_directory() ? FILE_ATTRIBUTE_DIRECTORY
|
||||
: FILE_ATTRIBUTE_ARCHIVE;
|
||||
}
|
||||
|
||||
api_meta_map meta;
|
||||
if (attributes != 0U) {
|
||||
auto next_attributes =
|
||||
attributes & static_cast<UINT32>(~FILE_ATTRIBUTE_NORMAL);
|
||||
if (next_attributes == 0U) {
|
||||
next_attributes = attributes;
|
||||
}
|
||||
meta[META_ATTRIBUTES] = std::to_string(next_attributes);
|
||||
}
|
||||
|
||||
if ((creation_time != 0U) && (creation_time != max_time)) {
|
||||
meta[META_CREATION] =
|
||||
std::to_string(utils::time::windows_time_to_unix_time(creation_time));
|
||||
}
|
||||
|
||||
if ((last_access_time != 0U) && (last_access_time != max_time)) {
|
||||
meta[META_ACCESSED] = std::to_string(
|
||||
utils::time::windows_time_to_unix_time(last_access_time));
|
||||
}
|
||||
|
||||
if ((last_write_time != 0U) && (last_write_time != max_time)) {
|
||||
meta[META_WRITTEN] =
|
||||
std::to_string(utils::time::windows_time_to_unix_time(last_write_time));
|
||||
}
|
||||
|
||||
if ((change_time != 0U) && (change_time != max_time)) {
|
||||
meta[META_CHANGED] =
|
||||
std::to_string(utils::time::windows_time_to_unix_time(change_time));
|
||||
meta[META_MODIFIED] =
|
||||
std::to_string(utils::time::windows_time_to_unix_time(change_time));
|
||||
}
|
||||
|
||||
return handle_error(provider_.set_item_meta(api_path, meta));
|
||||
}
|
||||
|
||||
void winfsp_drive::set_file_info(remote::file_info &dest,
|
||||
@ -1090,19 +1114,9 @@ auto winfsp_drive::SetFileSize(PVOID /*file_node*/, PVOID file_desc,
|
||||
std::string api_path;
|
||||
std::shared_ptr<i_open_file> file;
|
||||
const auto handle_error = [this, &api_path, &file,
|
||||
&file_info](auto error) -> NTSTATUS {
|
||||
auto ret = utils::from_api_error(error);
|
||||
RAISE_WINFSP_EVENT(function_name, api_path, ret);
|
||||
|
||||
if (file_info != nullptr && file && error == api_error::success) {
|
||||
// Populate file information
|
||||
api_meta_map meta;
|
||||
if (provider_.get_item_meta(api_path, meta) == api_error::success) {
|
||||
populate_file_info(file->get_file_size(), meta, *file_info);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
&file_info](api_error error) -> NTSTATUS {
|
||||
return this->handle_error(function_name, api_path, error, file_info,
|
||||
file ? file->get_file_size() : 0U);
|
||||
};
|
||||
|
||||
auto handle =
|
||||
@ -1146,8 +1160,7 @@ VOID winfsp_drive::Unmounted(PVOID host) {
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
||||
auto *file_system_host = reinterpret_cast<FileSystemHost *>(host);
|
||||
const auto mount_location =
|
||||
parse_mount_location(file_system_host->MountPoint());
|
||||
auto mount_location = parse_mount_location(file_system_host->MountPoint());
|
||||
event_system::instance().raise<drive_unmount_pending>(mount_location);
|
||||
if (remote_server_) {
|
||||
remote_server_.reset();
|
||||
@ -1180,55 +1193,50 @@ auto winfsp_drive::Write(PVOID /*file_node*/, PVOID file_desc, PVOID buffer,
|
||||
*bytes_transferred = 0;
|
||||
|
||||
std::string api_path;
|
||||
auto error = api_error::invalid_handle;
|
||||
std::shared_ptr<i_open_file> file;
|
||||
const auto handle_error = [this, &api_path, &file,
|
||||
&file_info](api_error error) -> NTSTATUS {
|
||||
return this->handle_error(function_name, api_path, error, file_info,
|
||||
file ? file->get_file_size() : 0U, true);
|
||||
};
|
||||
|
||||
auto handle =
|
||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
||||
if (handle != 0U) {
|
||||
std::shared_ptr<i_open_file> file;
|
||||
if (fm_->get_open_file(handle, true, file)) {
|
||||
api_path = file->get_api_path();
|
||||
if (write_to_end != 0U) {
|
||||
offset = file->get_file_size();
|
||||
}
|
||||
if (handle == 0U || not fm_->get_open_file(handle, true, file)) {
|
||||
return handle_error(api_error::invalid_handle);
|
||||
}
|
||||
|
||||
auto should_write = true;
|
||||
if (constrained_io != 0U) {
|
||||
if (offset >= file->get_file_size()) {
|
||||
error = api_error::success;
|
||||
should_write = false;
|
||||
} else if (offset + length > file->get_file_size()) {
|
||||
length = static_cast<ULONG>(file->get_file_size() - offset);
|
||||
}
|
||||
}
|
||||
api_path = file->get_api_path();
|
||||
if (write_to_end != 0U) {
|
||||
offset = file->get_file_size();
|
||||
}
|
||||
|
||||
if (should_write) {
|
||||
if (length > 0U) {
|
||||
std::size_t bytes_written{};
|
||||
data_buffer data(length);
|
||||
std::memcpy(data.data(), buffer, length);
|
||||
error = file->write(offset, data, bytes_written);
|
||||
if (error == api_error::success) {
|
||||
*bytes_transferred = static_cast<ULONG>(bytes_written);
|
||||
auto should_write{true};
|
||||
if (constrained_io != 0U) {
|
||||
if (offset >= file->get_file_size()) {
|
||||
return handle_error(api_error::success);
|
||||
}
|
||||
|
||||
// Populate file information
|
||||
api_meta_map meta;
|
||||
if (provider_.get_item_meta(api_path, meta) == api_error::success) {
|
||||
populate_file_info(file->get_file_size(), meta, *file_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error = api_error::success;
|
||||
}
|
||||
if (offset + length > file->get_file_size()) {
|
||||
length = static_cast<ULONG>(file->get_file_size() - offset);
|
||||
}
|
||||
}
|
||||
|
||||
auto ret = utils::from_api_error(error);
|
||||
if (ret != STATUS_SUCCESS) {
|
||||
RAISE_WINFSP_EVENT(function_name, api_path, ret);
|
||||
if (length == 0U) {
|
||||
return handle_error(api_error::success);
|
||||
}
|
||||
|
||||
return ret;
|
||||
std::size_t bytes_written{};
|
||||
data_buffer data(length);
|
||||
std::memcpy(data.data(), buffer, length);
|
||||
|
||||
auto res = file->write(offset, data, bytes_written);
|
||||
if (res != api_error::success) {
|
||||
return handle_error(res);
|
||||
}
|
||||
|
||||
*bytes_transferred = static_cast<ULONG>(bytes_written);
|
||||
return handle_error(api_error::success);
|
||||
}
|
||||
} // namespace repertory
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user