refactor
This commit is contained in:
parent
d07e1f9cce
commit
c22c68ef28
@ -75,8 +75,14 @@ private:
|
|||||||
std::unique_ptr<remote_winfsp::remote_server> remote_server_;
|
std::unique_ptr<remote_winfsp::remote_server> remote_server_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static auto
|
[[nodiscard]] auto handle_error(std::string_view function_name,
|
||||||
parse_mount_location(const std::wstring &mount_location) -> std::string;
|
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,
|
void populate_file_info(const std::string &api_path, std::uint64_t file_size,
|
||||||
const api_meta_map &meta,
|
const api_meta_map &meta,
|
||||||
@ -89,8 +95,8 @@ private:
|
|||||||
const FSP_FSCTL_FILE_INFO &src);
|
const FSP_FSCTL_FILE_INFO &src);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
auto CanDelete(PVOID file_node, PVOID file_desc,
|
auto CanDelete(PVOID file_node, PVOID file_desc, PWSTR file_name)
|
||||||
PWSTR file_name) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
VOID Cleanup(PVOID file_node, PVOID file_desc, PWSTR file_name,
|
VOID Cleanup(PVOID file_node, PVOID file_desc, PWSTR file_name,
|
||||||
ULONG flags) override;
|
ULONG flags) override;
|
||||||
@ -102,8 +108,8 @@ public:
|
|||||||
UINT64 allocation_size, PVOID *file_node, PVOID *file_desc,
|
UINT64 allocation_size, PVOID *file_node, PVOID *file_desc,
|
||||||
OpenFileInfo *ofi) -> NTSTATUS override;
|
OpenFileInfo *ofi) -> NTSTATUS override;
|
||||||
|
|
||||||
auto Flush(PVOID file_node, PVOID file_desc,
|
auto Flush(PVOID file_node, PVOID file_desc, FileInfo *file_info)
|
||||||
FileInfo *file_info) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_directory_item_count(const std::string &api_path) const
|
[[nodiscard]] auto get_directory_item_count(const std::string &api_path) const
|
||||||
-> std::uint64_t override;
|
-> std::uint64_t override;
|
||||||
@ -111,24 +117,25 @@ public:
|
|||||||
[[nodiscard]] auto get_directory_items(const std::string &api_path) const
|
[[nodiscard]] auto get_directory_items(const std::string &api_path) const
|
||||||
-> directory_item_list override;
|
-> directory_item_list override;
|
||||||
|
|
||||||
auto GetFileInfo(PVOID file_node, PVOID file_desc,
|
auto GetFileInfo(PVOID file_node, PVOID file_desc, FileInfo *file_info)
|
||||||
FileInfo *file_info) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto get_file_size(const std::string &api_path) const
|
||||||
get_file_size(const std::string &api_path) const -> std::uint64_t override;
|
-> std::uint64_t override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto get_item_meta(const std::string &api_path,
|
||||||
get_item_meta(const std::string &api_path,
|
api_meta_map &meta) const
|
||||||
api_meta_map &meta) const -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto get_item_meta(const std::string &api_path,
|
||||||
get_item_meta(const std::string &api_path, const std::string &name,
|
const std::string &name,
|
||||||
std::string &value) const -> api_error override;
|
std::string &value) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto get_security_by_name(PWSTR file_name, PUINT32 attributes,
|
||||||
get_security_by_name(PWSTR file_name, PUINT32 attributes,
|
PSECURITY_DESCRIPTOR descriptor,
|
||||||
PSECURITY_DESCRIPTOR descriptor,
|
std::uint64_t *descriptor_size)
|
||||||
std::uint64_t *descriptor_size) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
auto GetSecurityByName(PWSTR file_name, PUINT32 attributes,
|
auto GetSecurityByName(PWSTR file_name, PUINT32 attributes,
|
||||||
PSECURITY_DESCRIPTOR descriptor,
|
PSECURITY_DESCRIPTOR descriptor,
|
||||||
@ -152,16 +159,16 @@ public:
|
|||||||
auto Mounted(PVOID host) -> NTSTATUS override;
|
auto Mounted(PVOID host) -> NTSTATUS override;
|
||||||
|
|
||||||
auto Open(PWSTR file_name, UINT32 create_options, UINT32 granted_access,
|
auto Open(PWSTR file_name, UINT32 create_options, UINT32 granted_access,
|
||||||
PVOID *file_node, PVOID *file_desc,
|
PVOID *file_node, PVOID *file_desc, OpenFileInfo *ofi)
|
||||||
OpenFileInfo *ofi) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
auto Overwrite(PVOID file_node, PVOID file_desc, UINT32 attributes,
|
auto Overwrite(PVOID file_node, PVOID file_desc, UINT32 attributes,
|
||||||
BOOLEAN replace_attributes, UINT64 allocation_size,
|
BOOLEAN replace_attributes, UINT64 allocation_size,
|
||||||
FileInfo *file_info) -> NTSTATUS override;
|
FileInfo *file_info) -> NTSTATUS override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto populate_file_info(const std::string &api_path,
|
||||||
populate_file_info(const std::string &api_path,
|
remote::file_info &file_info)
|
||||||
remote::file_info &file_info) -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
auto Read(PVOID file_node, PVOID file_desc, PVOID buffer, UINT64 offset,
|
auto Read(PVOID file_node, PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||||
ULONG length, PULONG bytes_transferred) -> NTSTATUS override;
|
ULONG length, PULONG bytes_transferred) -> NTSTATUS override;
|
||||||
@ -171,8 +178,8 @@ public:
|
|||||||
PULONG bytes_transferred) -> NTSTATUS override;
|
PULONG bytes_transferred) -> NTSTATUS override;
|
||||||
|
|
||||||
auto Rename(PVOID file_node, PVOID file_desc, PWSTR file_name,
|
auto Rename(PVOID file_node, PVOID file_desc, PWSTR file_name,
|
||||||
PWSTR new_file_name,
|
PWSTR new_file_name, BOOLEAN replace_if_exists)
|
||||||
BOOLEAN replace_if_exists) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
auto SetBasicInfo(PVOID file_node, PVOID file_desc, UINT32 attributes,
|
auto SetBasicInfo(PVOID file_node, PVOID file_desc, UINT32 attributes,
|
||||||
UINT64 creation_time, UINT64 last_access_time,
|
UINT64 creation_time, UINT64 last_access_time,
|
||||||
@ -180,15 +187,15 @@ public:
|
|||||||
FileInfo *file_info) -> NTSTATUS override;
|
FileInfo *file_info) -> NTSTATUS override;
|
||||||
|
|
||||||
auto SetFileSize(PVOID file_node, PVOID file_desc, UINT64 new_size,
|
auto SetFileSize(PVOID file_node, PVOID file_desc, UINT64 new_size,
|
||||||
BOOLEAN set_allocation_size,
|
BOOLEAN set_allocation_size, FileInfo *file_info)
|
||||||
FileInfo *file_info) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
VOID Unmounted(PVOID host) override;
|
VOID Unmounted(PVOID host) override;
|
||||||
|
|
||||||
auto Write(PVOID file_node, PVOID file_desc, PVOID buffer, UINT64 offset,
|
auto Write(PVOID file_node, PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||||
ULONG length, BOOLEAN write_to_end, BOOLEAN constrained_io,
|
ULONG length, BOOLEAN write_to_end, BOOLEAN constrained_io,
|
||||||
PULONG bytes_transferred,
|
PULONG bytes_transferred, FileInfo *file_info)
|
||||||
FileInfo *file_info) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
void shutdown();
|
void shutdown();
|
||||||
|
|
||||||
|
@ -67,13 +67,35 @@ winfsp_drive::winfsp_service::winfsp_service(
|
|||||||
host_(drive),
|
host_(drive),
|
||||||
config_(config) {}
|
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*/)
|
auto winfsp_drive::winfsp_service::OnStart(ULONG /*Argc*/, PWSTR * /*Argv*/)
|
||||||
-> NTSTATUS {
|
-> NTSTATUS {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
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] : ""));
|
utils::path::absolute((drive_args_.size() > 1U) ? drive_args_[1U] : ""));
|
||||||
const auto drive_letter =
|
auto drive_letter =
|
||||||
((mount_location.size() == 2U) ||
|
((mount_location.size() == 2U) ||
|
||||||
((mount_location.size() == 3U) && (mount_location[2U] == '\\'))) &&
|
((mount_location.size() == 3U) && (mount_location[2U] == '\\'))) &&
|
||||||
(mount_location[1U] == ':');
|
(mount_location[1U] == ':');
|
||||||
@ -132,27 +154,26 @@ auto winfsp_drive::CanDelete(PVOID /*file_node*/, PVOID file_desc,
|
|||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
std::string api_path;
|
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 =
|
auto handle =
|
||||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
||||||
if (handle != 0U) {
|
if (handle == 0U || not fm_->get_open_file(handle, false, file)) {
|
||||||
std::shared_ptr<i_open_file> file;
|
return handle_error(api_error::invalid_handle);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ret = utils::from_api_error(error);
|
api_path = file->get_api_path();
|
||||||
RAISE_WINFSP_EVENT(function_name, api_path, ret);
|
if (file->is_directory()) {
|
||||||
return ret;
|
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,
|
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();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
std::string api_path;
|
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 =
|
auto handle =
|
||||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
||||||
if (handle != 0U) {
|
if (handle == 0U || not fm_->get_open_file(handle, false, file)) {
|
||||||
std::shared_ptr<i_open_file> file;
|
return handle_error(api_error::invalid_handle);
|
||||||
if (fm_->get_open_file(handle, false, file)) {
|
}
|
||||||
api_path = file->get_api_path();
|
|
||||||
|
|
||||||
const auto directory = file->is_directory();
|
api_path = file->get_api_path();
|
||||||
if ((flags & FspCleanupDelete) != 0U) {
|
|
||||||
auto *directory_buffer = file->get_open_data(handle).directory_buffer;
|
|
||||||
file.reset();
|
|
||||||
|
|
||||||
if (directory_buffer != nullptr) {
|
auto directory = file->is_directory();
|
||||||
FspFileSystemDeleteDirectoryBuffer(&directory_buffer);
|
if ((flags & FspCleanupDelete) != 0U) {
|
||||||
}
|
auto *directory_buffer = file->get_open_data(handle).directory_buffer;
|
||||||
|
file.reset();
|
||||||
|
|
||||||
if (directory) {
|
if (directory_buffer != nullptr) {
|
||||||
if (provider_.get_directory_item_count(api_path) == 0) {
|
FspFileSystemDeleteDirectoryBuffer(&directory_buffer);
|
||||||
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 ((flags & (FspCleanupSetLastAccessTime | FspCleanupSetLastWriteTime |
|
if (directory) {
|
||||||
FspCleanupSetChangeTime)) != 0U) {
|
if (provider_.get_directory_item_count(api_path) == 0) {
|
||||||
const auto now = utils::time::get_time_now();
|
return handle_error(provider_.remove_directory(api_path));
|
||||||
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) {
|
return handle_error(api_error::directory_not_empty);
|
||||||
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) {
|
return handle_error(fm_->remove_file(api_path));
|
||||||
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) {
|
if (((flags & FspCleanupSetArchiveBit) != 0U) && not directory) {
|
||||||
auto allocation_size =
|
api_meta_map meta;
|
||||||
utils::divide_with_ceiling(file->get_file_size(),
|
if (provider_.get_item_meta(api_path, meta) == api_error::success) {
|
||||||
WINFSP_ALLOCATION_UNIT) *
|
auto res = provider_.set_item_meta(
|
||||||
WINFSP_ALLOCATION_UNIT;
|
api_path, META_ATTRIBUTES,
|
||||||
SetFileSize(file_node, file_desc, allocation_size, TRUE, nullptr);
|
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) {
|
VOID winfsp_drive::Close(PVOID /*file_node*/, PVOID file_desc) {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
std::string api_path;
|
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 =
|
auto handle =
|
||||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
||||||
if (handle != 0U) {
|
if (handle == 0U || not fm_->get_open_file(handle, false, file)) {
|
||||||
PVOID directory_buffer{nullptr};
|
return handle_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();
|
|
||||||
directory_buffer = file->get_open_data(handle).directory_buffer;
|
|
||||||
file.reset();
|
|
||||||
}
|
|
||||||
fm_->close(handle);
|
|
||||||
if (directory_buffer != nullptr) {
|
|
||||||
FspFileSystemDeleteDirectoryBuffer(&directory_buffer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
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;
|
attributes |= FILE_ATTRIBUTE_ARCHIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto now = utils::time::get_time_now();
|
auto now = utils::time::get_time_now();
|
||||||
auto meta = create_meta_attributes(
|
auto meta = create_meta_attributes(
|
||||||
now, attributes, now, now, (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0U,
|
now, attributes, now, now, (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0U,
|
||||||
0U, "", 0U, now, 0U, 0U, 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()}),
|
{utils::create_uuid_string()}),
|
||||||
0U, now);
|
0U, now);
|
||||||
|
|
||||||
const auto api_path =
|
auto api_path =
|
||||||
utils::path::create_api_path(utils::string::to_utf8(file_name));
|
utils::path::create_api_path(utils::string::to_utf8(file_name));
|
||||||
|
|
||||||
open_file_data ofd{};
|
open_file_data ofd{};
|
||||||
@ -350,33 +367,27 @@ auto winfsp_drive::Flush(PVOID /*file_node*/, PVOID file_desc,
|
|||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
std::string api_path;
|
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 =
|
auto handle =
|
||||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
||||||
if (handle != 0U) {
|
if (handle == 0U || not fm_->get_open_file(handle, false, file)) {
|
||||||
error = api_error::invalid_handle;
|
return handle_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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ret = utils::from_api_error(error);
|
api_path = file->get_api_path();
|
||||||
RAISE_WINFSP_EVENT(function_name, api_path, ret);
|
return handle_error(file->native_operation([&](native_handle op_handle) {
|
||||||
return ret;
|
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
|
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();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
std::string api_path;
|
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 =
|
auto handle =
|
||||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
||||||
if (handle != 0U) {
|
if (handle == 0U || not fm_->get_open_file(handle, false, file)) {
|
||||||
std::shared_ptr<i_open_file> file;
|
return handle_error(api_error::invalid_handle);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ret = utils::from_api_error(error);
|
return handle_error(api_error::success);
|
||||||
RAISE_WINFSP_EVENT(function_name, api_path, ret);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto winfsp_drive::get_file_size(const std::string &api_path) const
|
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,
|
PSECURITY_DESCRIPTOR descriptor,
|
||||||
std::uint64_t *descriptor_size)
|
std::uint64_t *descriptor_size)
|
||||||
-> NTSTATUS {
|
-> NTSTATUS {
|
||||||
const auto api_path =
|
auto api_path =
|
||||||
utils::path::create_api_path(utils::string::to_utf8(file_name));
|
utils::path::create_api_path(utils::string::to_utf8(file_name));
|
||||||
|
|
||||||
api_meta_map meta{};
|
api_meta_map meta{};
|
||||||
@ -494,7 +501,7 @@ auto winfsp_drive::GetSecurityByName(PWSTR file_name, PUINT32 attributes,
|
|||||||
SIZE_T *descriptor_size) -> NTSTATUS {
|
SIZE_T *descriptor_size) -> NTSTATUS {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto api_path =
|
auto api_path =
|
||||||
utils::path::create_api_path(utils::string::to_utf8(file_name));
|
utils::path::create_api_path(utils::string::to_utf8(file_name));
|
||||||
std::uint64_t sds = descriptor_size == nullptr ? 0U : *descriptor_size;
|
std::uint64_t sds = descriptor_size == nullptr ? 0U : *descriptor_size;
|
||||||
auto ret = get_security_by_name(file_name, attributes, descriptor,
|
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,
|
void winfsp_drive::get_volume_info(UINT64 &total_size, UINT64 &free_size,
|
||||||
std::string &volume_label) const {
|
std::string &volume_label) const {
|
||||||
const auto total_bytes = provider_.get_total_drive_space();
|
auto total_bytes = provider_.get_total_drive_space();
|
||||||
const auto total_used = provider_.get_used_drive_space();
|
auto total_used = provider_.get_used_drive_space();
|
||||||
free_size = total_bytes - total_used;
|
free_size = total_bytes - total_used;
|
||||||
total_size = total_bytes;
|
total_size = total_bytes;
|
||||||
volume_label = utils::create_volume_label(config_.get_provider_type());
|
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(
|
const std::wstring volume_label = utils::string::from_utf8(
|
||||||
utils::create_volume_label(config_.get_provider_type()));
|
utils::create_volume_label(config_.get_provider_type()));
|
||||||
const auto total_bytes = provider_.get_total_drive_space();
|
auto total_bytes = provider_.get_total_drive_space();
|
||||||
const auto total_used = provider_.get_used_drive_space();
|
auto total_used = provider_.get_used_drive_space();
|
||||||
volume_info->FreeSize = total_bytes - total_used;
|
volume_info->FreeSize = total_bytes - total_used;
|
||||||
volume_info->TotalSize = total_bytes;
|
volume_info->TotalSize = total_bytes;
|
||||||
wcscpy_s(&volume_info->VolumeLabel[0U], 32, volume_label.data());
|
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 {
|
auto winfsp_drive::mount(const std::vector<std::string> &drive_args) -> int {
|
||||||
std::vector<std::string> parsed_drive_args;
|
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;
|
auto enable_console = false;
|
||||||
for (auto &&arg : drive_args) {
|
for (auto &&arg : drive_args) {
|
||||||
@ -638,8 +645,7 @@ auto winfsp_drive::Mounted(PVOID host) -> NTSTATUS {
|
|||||||
eviction_->start();
|
eviction_->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto mount_location =
|
auto mount_location = parse_mount_location(file_system_host->MountPoint());
|
||||||
parse_mount_location(file_system_host->MountPoint());
|
|
||||||
if (config_.get_enable_remote_mount()) {
|
if (config_.get_enable_remote_mount()) {
|
||||||
remote_server_ = std::make_unique<remote_winfsp::remote_server>(
|
remote_server_ = std::make_unique<remote_winfsp::remote_server>(
|
||||||
config_, *this, mount_location);
|
config_, *this, mount_location);
|
||||||
@ -675,7 +681,7 @@ auto winfsp_drive::Open(PWSTR file_name, UINT32 create_options,
|
|||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
*file_desc = reinterpret_cast<PVOID>(INVALID_HANDLE_VALUE);
|
*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));
|
utils::path::create_api_path(utils::string::to_utf8(file_name));
|
||||||
|
|
||||||
bool directory{};
|
bool directory{};
|
||||||
@ -723,49 +729,58 @@ auto winfsp_drive::Overwrite(PVOID /*file_node*/, PVOID file_desc,
|
|||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
std::string api_path;
|
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 =
|
auto handle =
|
||||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
||||||
if (handle != 0U) {
|
if (handle == 0U || not fm_->get_open_file(handle, true, file)) {
|
||||||
std::shared_ptr<i_open_file> file;
|
return handle_error(api_error::invalid_handle);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ret = utils::from_api_error(error);
|
api_path = file->get_api_path();
|
||||||
RAISE_WINFSP_EVENT(function_name, api_path, ret);
|
api_meta_map meta{};
|
||||||
return ret;
|
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)
|
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,
|
std::uint64_t file_size,
|
||||||
const api_meta_map &meta,
|
const api_meta_map &meta,
|
||||||
FSP_FSCTL_OPEN_FILE_INFO &ofi) {
|
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, '/', '\\'));
|
utils::string::replace_copy(api_path, '/', '\\'));
|
||||||
|
|
||||||
wcscpy_s(ofi.NormalizedName, ofi.NormalizedNameSize / sizeof(WCHAR),
|
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;
|
*bytes_transferred = 0U;
|
||||||
|
|
||||||
std::string api_path;
|
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 =
|
auto handle =
|
||||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
||||||
if (handle != 0U) {
|
if (handle == 0U || not fm_->get_open_file(handle, false, file)) {
|
||||||
if (length > 0U) {
|
return handle_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();
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ret = utils::from_api_error(error);
|
api_path = file->get_api_path();
|
||||||
if (ret != STATUS_SUCCESS) {
|
|
||||||
RAISE_WINFSP_EVENT(function_name, api_path, ret);
|
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,
|
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;
|
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));
|
utils::path::strip_to_file_name(dir_item.api_path));
|
||||||
union {
|
union {
|
||||||
UINT8 B[FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) +
|
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 {
|
BOOLEAN replace_if_exists) -> NTSTATUS {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
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));
|
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));
|
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{};
|
bool exists{};
|
||||||
error = provider_.is_file(from_api_path, exists);
|
auto res = provider_.is_file(from_api_path, exists);
|
||||||
if (error == api_error::success) {
|
if res != api_error::success) {
|
||||||
if (exists) {
|
return handle_error(res);
|
||||||
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 ret = utils::from_api_error(error);
|
if (exists) {
|
||||||
RAISE_WINFSP_EVENT(function_name, from_api_path + "|" + to_api_path, ret);
|
return handle_error(
|
||||||
return ret;
|
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,
|
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();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
std::string api_path;
|
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 =
|
auto handle =
|
||||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
||||||
if (handle != 0U) {
|
if (handle == 0U || not fm_->get_open_file(handle, true, file)) {
|
||||||
std::shared_ptr<i_open_file> file;
|
return handle_error(api_error::invalid_handle);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ret = utils::from_api_error(error);
|
api_path = file->get_api_path();
|
||||||
RAISE_WINFSP_EVENT(function_name, api_path, ret);
|
if (attributes == INVALID_FILE_ATTRIBUTES) {
|
||||||
return ret;
|
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,
|
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::string api_path;
|
||||||
std::shared_ptr<i_open_file> file;
|
std::shared_ptr<i_open_file> file;
|
||||||
const auto handle_error = [this, &api_path, &file,
|
const auto handle_error = [this, &api_path, &file,
|
||||||
&file_info](auto error) -> NTSTATUS {
|
&file_info](api_error error) -> NTSTATUS {
|
||||||
auto ret = utils::from_api_error(error);
|
return this->handle_error(function_name, api_path, error, file_info,
|
||||||
RAISE_WINFSP_EVENT(function_name, api_path, ret);
|
file ? file->get_file_size() : 0U);
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
auto handle =
|
auto handle =
|
||||||
@ -1146,8 +1160,7 @@ VOID winfsp_drive::Unmounted(PVOID host) {
|
|||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
auto *file_system_host = reinterpret_cast<FileSystemHost *>(host);
|
auto *file_system_host = reinterpret_cast<FileSystemHost *>(host);
|
||||||
const auto mount_location =
|
auto mount_location = parse_mount_location(file_system_host->MountPoint());
|
||||||
parse_mount_location(file_system_host->MountPoint());
|
|
||||||
event_system::instance().raise<drive_unmount_pending>(mount_location);
|
event_system::instance().raise<drive_unmount_pending>(mount_location);
|
||||||
if (remote_server_) {
|
if (remote_server_) {
|
||||||
remote_server_.reset();
|
remote_server_.reset();
|
||||||
@ -1180,55 +1193,50 @@ auto winfsp_drive::Write(PVOID /*file_node*/, PVOID file_desc, PVOID buffer,
|
|||||||
*bytes_transferred = 0;
|
*bytes_transferred = 0;
|
||||||
|
|
||||||
std::string api_path;
|
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 =
|
auto handle =
|
||||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(file_desc));
|
||||||
if (handle != 0U) {
|
if (handle == 0U || not fm_->get_open_file(handle, true, file)) {
|
||||||
std::shared_ptr<i_open_file> file;
|
return handle_error(api_error::invalid_handle);
|
||||||
if (fm_->get_open_file(handle, true, file)) {
|
}
|
||||||
api_path = file->get_api_path();
|
|
||||||
if (write_to_end != 0U) {
|
|
||||||
offset = file->get_file_size();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto should_write = true;
|
api_path = file->get_api_path();
|
||||||
if (constrained_io != 0U) {
|
if (write_to_end != 0U) {
|
||||||
if (offset >= file->get_file_size()) {
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (should_write) {
|
auto should_write{true};
|
||||||
if (length > 0U) {
|
if (constrained_io != 0U) {
|
||||||
std::size_t bytes_written{};
|
if (offset >= file->get_file_size()) {
|
||||||
data_buffer data(length);
|
return handle_error(api_error::success);
|
||||||
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);
|
|
||||||
|
|
||||||
// Populate file information
|
if (offset + length > file->get_file_size()) {
|
||||||
api_meta_map meta;
|
length = static_cast<ULONG>(file->get_file_size() - offset);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ret = utils::from_api_error(error);
|
if (length == 0U) {
|
||||||
if (ret != STATUS_SUCCESS) {
|
return handle_error(api_error::success);
|
||||||
RAISE_WINFSP_EVENT(function_name, api_path, ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
} // namespace repertory
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user