1443 lines
52 KiB
C++
1443 lines
52 KiB
C++
/*
|
|
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE.
|
|
*/
|
|
#ifndef INCLUDE_DRIVES_REMOTE_REMOTE_SERVER_BASE_HPP_
|
|
#define INCLUDE_DRIVES_REMOTE_REMOTE_SERVER_BASE_HPP_
|
|
|
|
#include "app_config.hpp"
|
|
#include "comm/packet/client_pool.hpp"
|
|
#include "comm/packet/packet.hpp"
|
|
#include "comm/packet/packet_server.hpp"
|
|
#include "drives/directory_iterator.hpp"
|
|
#include "drives/fuse/remotefuse/i_remote_instance.hpp"
|
|
#include "drives/remote/i_remote_json.hpp"
|
|
#include "drives/remote/remote_open_file_table.hpp"
|
|
#include "drives/winfsp/remotewinfsp/i_remote_instance.hpp"
|
|
#include "types/remote.hpp"
|
|
#include "types/repertory.hpp"
|
|
#include "utils/Base64.hpp"
|
|
#include "utils/path_utils.hpp"
|
|
|
|
#define REPERTORY_DIRECTORY_PAGE_SIZE std::size_t(100u)
|
|
|
|
namespace repertory {
|
|
template <typename drive>
|
|
class remote_server_base : public remote_open_file_table,
|
|
public virtual remote_winfsp::i_remote_instance,
|
|
public virtual remote_fuse::i_remote_instance {
|
|
public:
|
|
remote_server_base(const remote_server_base &) = delete;
|
|
remote_server_base(remote_server_base &&) = delete;
|
|
auto operator=(const remote_server_base &) -> remote_server_base & = delete;
|
|
auto operator=(remote_server_base &&) -> remote_server_base & = delete;
|
|
|
|
public:
|
|
remote_server_base(app_config &config, drive &drv, std::string mount_location)
|
|
: config_(config),
|
|
drive_(drv),
|
|
mount_location_(std::move(mount_location)),
|
|
client_pool_(config.get_remote_client_pool_size()) {
|
|
event_system::instance().raise<service_started>("remote_server_base");
|
|
handler_lookup_.insert(
|
|
{"::winfsp_can_delete",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
auto ret = STATUS_SUCCESS;
|
|
|
|
HANDLE file_desc{};
|
|
DECODE_OR_RETURN(request, file_desc);
|
|
|
|
std::wstring file_name;
|
|
DECODE_OR_RETURN(request, file_name);
|
|
|
|
return this->winfsp_can_delete(file_desc, file_name.data());
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::winfsp_cleanup",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = STATUS_SUCCESS;
|
|
|
|
HANDLE file_desc{};
|
|
DECODE_OR_RETURN(request, file_desc);
|
|
|
|
std::wstring file_name;
|
|
DECODE_OR_RETURN(request, file_name);
|
|
|
|
UINT32 flags{};
|
|
DECODE_OR_RETURN(request, flags);
|
|
|
|
BOOLEAN was_closed{};
|
|
ret = this->winfsp_cleanup(file_desc, file_name.data(), flags,
|
|
was_closed);
|
|
response.encode(was_closed);
|
|
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::winfsp_close",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
auto ret = STATUS_SUCCESS;
|
|
|
|
HANDLE file_desc{};
|
|
DECODE_OR_RETURN(request, file_desc);
|
|
|
|
return this->winfsp_close(file_desc);
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::winfsp_create",
|
|
[this](std::uint32_t, const std::string &client_id, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = STATUS_SUCCESS;
|
|
|
|
std::wstring file_name;
|
|
DECODE_OR_RETURN(request, file_name);
|
|
|
|
UINT32 create_options{};
|
|
DECODE_OR_RETURN(request, create_options);
|
|
|
|
UINT32 granted_access{};
|
|
DECODE_OR_RETURN(request, granted_access);
|
|
|
|
UINT32 attributes{};
|
|
DECODE_OR_RETURN(request, attributes);
|
|
|
|
UINT64 allocation_size{};
|
|
DECODE_OR_RETURN(request, allocation_size);
|
|
|
|
BOOLEAN exists{0};
|
|
remote::file_info file_info{};
|
|
std::string normalized_name;
|
|
PVOID file_desc{};
|
|
ret = this->winfsp_create(file_name.data(), create_options,
|
|
granted_access, attributes,
|
|
allocation_size, &file_desc, &file_info,
|
|
normalized_name, exists);
|
|
if (ret == STATUS_SUCCESS) {
|
|
#ifdef _WIN32
|
|
this->set_client_id(file_desc, client_id);
|
|
#else
|
|
this->set_client_id(
|
|
static_cast<native_handle>(
|
|
reinterpret_cast<std::uintptr_t>(file_desc)),
|
|
client_id);
|
|
#endif
|
|
response.encode(file_desc);
|
|
response.encode(file_info);
|
|
response.encode(normalized_name);
|
|
response.encode(exists);
|
|
}
|
|
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::winfsp_flush",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = STATUS_SUCCESS;
|
|
|
|
HANDLE file_desc{};
|
|
DECODE_OR_RETURN(request, file_desc);
|
|
|
|
remote::file_info file_info{};
|
|
ret = this->winfsp_flush(file_desc, &file_info);
|
|
if (ret == STATUS_SUCCESS) {
|
|
response.encode(file_info);
|
|
}
|
|
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::winfsp_get_file_info",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = STATUS_SUCCESS;
|
|
|
|
HANDLE file_desc{};
|
|
DECODE_OR_RETURN(request, file_desc);
|
|
|
|
remote::file_info file_info{};
|
|
ret = this->winfsp_get_file_info(file_desc, &file_info);
|
|
if (ret == STATUS_SUCCESS) {
|
|
response.encode(file_info);
|
|
}
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::winfsp_get_security_by_name",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = STATUS_SUCCESS;
|
|
|
|
std::wstring file_name;
|
|
DECODE_OR_RETURN(request, file_name);
|
|
|
|
std::uint64_t descriptor_size{};
|
|
DECODE_OR_RETURN(request, descriptor_size);
|
|
|
|
std::uint8_t get_attributes{};
|
|
DECODE_OR_RETURN(request, get_attributes);
|
|
|
|
UINT32 attributes{};
|
|
auto *attr_ptr = get_attributes == 0U ? nullptr : &attributes;
|
|
std::wstring string_descriptor;
|
|
ret = this->winfsp_get_security_by_name(
|
|
file_name.data(), attr_ptr,
|
|
descriptor_size == 0U ? nullptr : &descriptor_size,
|
|
string_descriptor);
|
|
if (ret == STATUS_SUCCESS) {
|
|
response.encode(string_descriptor);
|
|
if (get_attributes != 0U) {
|
|
response.encode(attributes);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert({"::winfsp_get_volume_info",
|
|
[this](std::uint32_t, const std::string &,
|
|
std::uint64_t, const std::string &, packet *,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = STATUS_SUCCESS;
|
|
|
|
UINT64 total_size{};
|
|
UINT64 free_size{};
|
|
std::string volume_label;
|
|
if ((ret = this->winfsp_get_volume_info(
|
|
total_size, free_size, volume_label)) ==
|
|
STATUS_SUCCESS) {
|
|
response.encode(total_size);
|
|
response.encode(free_size);
|
|
response.encode(volume_label);
|
|
}
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::winfsp_mounted",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
auto ret = STATUS_SUCCESS;
|
|
|
|
std::string version;
|
|
DECODE_OR_RETURN(request, version);
|
|
|
|
std::wstring location;
|
|
DECODE_OR_RETURN(request, location);
|
|
|
|
ret = this->winfsp_mounted(location);
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::winfsp_open",
|
|
[this](std::uint32_t, const std::string &client_id, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = STATUS_SUCCESS;
|
|
|
|
std::wstring file_name;
|
|
DECODE_OR_RETURN(request, file_name);
|
|
|
|
UINT32 create_options{};
|
|
DECODE_OR_RETURN(request, create_options);
|
|
|
|
UINT32 granted_access{};
|
|
DECODE_OR_RETURN(request, granted_access);
|
|
|
|
remote::file_info file_info{};
|
|
std::string normalized_name;
|
|
PVOID file_desc{};
|
|
ret = this->winfsp_open(file_name.data(), create_options,
|
|
granted_access, &file_desc, &file_info,
|
|
normalized_name);
|
|
if (ret == STATUS_SUCCESS) {
|
|
#ifdef _WIN32
|
|
this->set_client_id(file_desc, client_id);
|
|
#else
|
|
this->set_client_id(
|
|
static_cast<native_handle>(
|
|
reinterpret_cast<std::uintptr_t>(file_desc)),
|
|
client_id);
|
|
#endif
|
|
response.encode(file_desc);
|
|
response.encode(file_info);
|
|
response.encode(normalized_name);
|
|
}
|
|
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::winfsp_overwrite",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = STATUS_SUCCESS;
|
|
|
|
HANDLE file_desc{};
|
|
DECODE_OR_RETURN(request, file_desc);
|
|
|
|
UINT32 attributes{};
|
|
DECODE_OR_RETURN(request, attributes);
|
|
|
|
BOOLEAN replace_attributes{};
|
|
DECODE_OR_RETURN(request, replace_attributes);
|
|
|
|
UINT64 allocation_size{};
|
|
DECODE_OR_RETURN(request, allocation_size);
|
|
|
|
remote::file_info file_info{};
|
|
ret =
|
|
this->winfsp_overwrite(file_desc, attributes, replace_attributes,
|
|
allocation_size, &file_info);
|
|
if (ret == STATUS_SUCCESS) {
|
|
response.encode(file_info);
|
|
}
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::winfsp_read",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = STATUS_SUCCESS;
|
|
|
|
HANDLE file_desc{};
|
|
DECODE_OR_RETURN(request, file_desc);
|
|
|
|
UINT64 offset{};
|
|
DECODE_OR_RETURN(request, offset);
|
|
|
|
UINT32 length{};
|
|
DECODE_OR_RETURN(request, length);
|
|
|
|
data_buffer buffer(length);
|
|
UINT32 bytes_transferred = 0;
|
|
ret = this->winfsp_read(file_desc, buffer.data(), offset, length,
|
|
&bytes_transferred);
|
|
if (ret == STATUS_SUCCESS) {
|
|
response.encode(bytes_transferred);
|
|
if (bytes_transferred != 0U) {
|
|
response.encode(buffer.data(), bytes_transferred);
|
|
}
|
|
}
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::winfsp_read_directory",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = STATUS_SUCCESS;
|
|
|
|
HANDLE file_desc{};
|
|
DECODE_OR_RETURN(request, file_desc);
|
|
|
|
std::wstring pattern;
|
|
DECODE_OR_IGNORE(request, pattern);
|
|
|
|
std::wstring marker;
|
|
DECODE_OR_IGNORE(request, marker);
|
|
|
|
json item_list;
|
|
ret = this->winfsp_read_directory(
|
|
file_desc, pattern.data(),
|
|
wcsnlen(marker.data(), marker.size()) == 0U ? nullptr
|
|
: marker.data(),
|
|
item_list);
|
|
if (ret == STATUS_SUCCESS) {
|
|
response.encode(item_list.dump(0));
|
|
}
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::winfsp_rename",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
auto ret = STATUS_SUCCESS;
|
|
|
|
HANDLE file_desc{};
|
|
DECODE_OR_RETURN(request, file_desc);
|
|
|
|
std::wstring file_name;
|
|
DECODE_OR_RETURN(request, file_name);
|
|
|
|
std::wstring new_file_name;
|
|
DECODE_OR_RETURN(request, new_file_name);
|
|
|
|
BOOLEAN replace_if_exists{};
|
|
DECODE_OR_RETURN(request, replace_if_exists);
|
|
|
|
ret = this->winfsp_rename(file_desc, file_name.data(),
|
|
new_file_name.data(), replace_if_exists);
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::winfsp_set_basic_info",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = STATUS_SUCCESS;
|
|
|
|
HANDLE file_desc{};
|
|
DECODE_OR_RETURN(request, file_desc);
|
|
|
|
UINT32 attributes{};
|
|
DECODE_OR_RETURN(request, attributes);
|
|
|
|
UINT64 creation_time{};
|
|
DECODE_OR_RETURN(request, creation_time);
|
|
|
|
UINT64 last_access_time{};
|
|
DECODE_OR_RETURN(request, last_access_time);
|
|
|
|
UINT64 last_write_time{};
|
|
DECODE_OR_RETURN(request, last_write_time);
|
|
|
|
UINT64 change_time{};
|
|
DECODE_OR_RETURN(request, change_time);
|
|
|
|
remote::file_info file_info{};
|
|
ret = this->winfsp_set_basic_info(
|
|
file_desc, attributes, creation_time, last_access_time,
|
|
last_write_time, change_time, &file_info);
|
|
if (ret == STATUS_SUCCESS) {
|
|
response.encode(file_info);
|
|
}
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::winfsp_set_file_size",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = STATUS_SUCCESS;
|
|
|
|
HANDLE file_desc{};
|
|
DECODE_OR_RETURN(request, file_desc);
|
|
|
|
UINT64 new_size{};
|
|
DECODE_OR_RETURN(request, new_size);
|
|
|
|
BOOLEAN set_allocation_size{};
|
|
DECODE_OR_RETURN(request, set_allocation_size);
|
|
|
|
remote::file_info file_info{};
|
|
ret = this->winfsp_set_file_size(file_desc, new_size,
|
|
set_allocation_size, &file_info);
|
|
if (ret == STATUS_SUCCESS) {
|
|
response.encode(file_info);
|
|
}
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::winfsp_unmounted",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
auto ret = STATUS_SUCCESS;
|
|
|
|
std::wstring location;
|
|
DECODE_OR_RETURN(request, location);
|
|
|
|
return this->winfsp_unmounted(location);
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::winfsp_write",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = STATUS_SUCCESS;
|
|
|
|
HANDLE file_desc{};
|
|
DECODE_OR_RETURN(request, file_desc);
|
|
|
|
UINT32 length{};
|
|
DECODE_OR_RETURN(request, length);
|
|
|
|
UINT64 offset{};
|
|
DECODE_OR_RETURN(request, offset);
|
|
|
|
BOOLEAN write_to_end{};
|
|
DECODE_OR_RETURN(request, write_to_end);
|
|
|
|
BOOLEAN constrained_io{};
|
|
DECODE_OR_RETURN(request, constrained_io);
|
|
|
|
auto *buffer = request->current_pointer();
|
|
|
|
UINT32 bytes_transferred = 0;
|
|
remote::file_info file_info{};
|
|
ret = this->winfsp_write(file_desc, buffer, offset, length,
|
|
write_to_end, constrained_io,
|
|
&bytes_transferred, &file_info);
|
|
if (ret == STATUS_SUCCESS) {
|
|
response.encode(bytes_transferred);
|
|
response.encode(file_info);
|
|
}
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_access",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
std::int32_t mask{};
|
|
DECODE_OR_RETURN(request, mask);
|
|
|
|
return this->fuse_access(path.data(), mask);
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_chflags",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
std::uint32_t flags{};
|
|
DECODE_OR_RETURN(request, flags);
|
|
|
|
return this->fuse_chflags(path.data(), flags);
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_chmod",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_mode mode;
|
|
DECODE_OR_RETURN(request, mode);
|
|
|
|
return this->fuse_chmod(&path[0], mode);
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_chown",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::user_id uid{};
|
|
DECODE_OR_RETURN(request, uid);
|
|
|
|
remote::group_id gid{};
|
|
DECODE_OR_RETURN(request, gid);
|
|
|
|
return this->fuse_chown(&path[0], uid, gid);
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_create",
|
|
[this](std::uint32_t, const std::string &client_id, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_mode mode{};
|
|
DECODE_OR_RETURN(request, mode);
|
|
|
|
remote::open_flags flags{};
|
|
DECODE_OR_RETURN(request, flags);
|
|
|
|
remote::file_handle handle{};
|
|
if ((ret = this->fuse_create(path.data(), mode, flags, handle)) >=
|
|
0) {
|
|
#ifdef _WIN32
|
|
this->set_compat_client_id(handle, client_id);
|
|
#else
|
|
this->set_client_id(static_cast<native_handle>(handle), client_id);
|
|
#endif
|
|
response.encode(handle);
|
|
}
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_destroy",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *, packet &) -> packet::error_type {
|
|
return this->fuse_destroy();
|
|
}});
|
|
/*handlerLookup_.insert({"::fuse_fallocate",
|
|
[this](std::uint32_t serviceFlags, const std::string
|
|
&client_id, std::uint64_t threadId, const std::string &method, packet
|
|
*request, packet &response) -> packet::error_type { auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
std::int32_t mode;
|
|
DECODE_OR_RETURN(request, mode);
|
|
|
|
remote::file_offset offset;
|
|
DECODE_OR_RETURN(request, offset);
|
|
|
|
remote::file_offset length;
|
|
DECODE_OR_RETURN(request, length);
|
|
|
|
remote::file_handle handle;
|
|
DECODE_OR_RETURN(request, handle);
|
|
|
|
return this->fuse_fallocate(&path[0], mode, offset,
|
|
length, handle);
|
|
}});*/
|
|
handler_lookup_.insert(
|
|
{"::fuse_fgetattr",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_handle handle{};
|
|
DECODE_OR_RETURN(request, handle);
|
|
|
|
remote::user_id uid{};
|
|
DECODE_OR_RETURN(request, uid);
|
|
|
|
remote::group_id gid{};
|
|
DECODE_OR_RETURN(request, gid);
|
|
|
|
remote::stat st{};
|
|
bool directory = false;
|
|
ret = this->fuse_fgetattr(path.data(), st, directory, handle);
|
|
if (ret == 0) {
|
|
st.st_uid = uid;
|
|
st.st_gid = gid;
|
|
response.encode(st);
|
|
response.encode(static_cast<std::uint8_t>(directory));
|
|
}
|
|
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_fsetattr_x",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::setattr_x attr{};
|
|
DECODE_OR_RETURN(request, attr);
|
|
|
|
remote::file_handle handle{};
|
|
DECODE_OR_RETURN(request, handle);
|
|
|
|
return this->fuse_fsetattr_x(path.data(), attr, handle);
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_fsync",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
std::int32_t dataSync;
|
|
DECODE_OR_RETURN(request, dataSync);
|
|
|
|
remote::file_handle handle;
|
|
DECODE_OR_RETURN(request, handle);
|
|
|
|
return this->fuse_fsync(&path[0], dataSync, handle);
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_ftruncate",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_offset size;
|
|
DECODE_OR_RETURN(request, size);
|
|
|
|
remote::file_handle handle;
|
|
DECODE_OR_RETURN(request, handle);
|
|
|
|
return this->fuse_ftruncate(&path[0], size, handle);
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_getattr",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::user_id uid;
|
|
DECODE_OR_RETURN(request, uid);
|
|
|
|
remote::group_id gid;
|
|
DECODE_OR_RETURN(request, gid);
|
|
|
|
remote::stat st{};
|
|
bool directory = false;
|
|
ret = this->fuse_getattr(&path[0], st, directory);
|
|
if (ret == 0) {
|
|
st.st_uid = uid;
|
|
st.st_gid = gid;
|
|
response.encode(st);
|
|
response.encode(static_cast<std::uint8_t>(directory));
|
|
}
|
|
return ret;
|
|
}});
|
|
/*handlerLookup_.insert({"::fuse_getxattr",
|
|
[this](std::uint32_t serviceFlags, const std::string
|
|
&client_id, std::uint64_t threadId, const std::string &method, packet
|
|
*request, packet &response) -> packet::error_type { auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
std::string name;
|
|
DECODE_OR_RETURN(request, name);
|
|
|
|
remote::file_size size;
|
|
DECODE_OR_RETURN(request, size);
|
|
|
|
return this->fuse_getxattr(&path[0], &name[0],
|
|
nullptr, size);
|
|
}});
|
|
handlerLookup_.insert({"::fuse_getxattr_osx",
|
|
[this](std::uint32_t serviceFlags, const std::string
|
|
&client_id, std::uint64_t threadId, const std::string &method, packet
|
|
*request, packet &response) -> packet::error_type { auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
std::string name;
|
|
DECODE_OR_RETURN(request, name);
|
|
|
|
remote::file_size size;
|
|
DECODE_OR_RETURN(request, size);
|
|
|
|
std::uint32_t position;
|
|
DECODE_OR_RETURN(request, position);
|
|
|
|
return this->fuse_getxattr_osx(&path[0], &name[0],
|
|
nullptr, size, position);
|
|
}});*/
|
|
handler_lookup_.insert(
|
|
{"::fuse_getxtimes",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_time bkuptime{};
|
|
remote::file_time crtime{};
|
|
if ((ret = this->fuse_getxtimes(&path[0], bkuptime, crtime)) == 0) {
|
|
response.encode(bkuptime);
|
|
response.encode(crtime);
|
|
}
|
|
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_init",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *,
|
|
packet &) -> packet::error_type { return this->fuse_init(); }});
|
|
/*handlerLookup_.insert({"::remote_fuseListxattr",
|
|
[this](std::uint32_t serviceFlags, const std::string
|
|
&client_id, std::uint64_t threadId, const std::string &method, packet
|
|
*request, packet &response) -> packet::error_type { auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_size size;
|
|
DECODE_OR_RETURN(request, size);
|
|
|
|
return this->fuse_listxattr(&path[0], nullptr,
|
|
size);
|
|
}});*/
|
|
handler_lookup_.insert(
|
|
{"::fuse_mkdir",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_mode mode;
|
|
DECODE_OR_RETURN(request, mode);
|
|
|
|
return this->fuse_mkdir(&path[0], mode);
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_open",
|
|
[this](std::uint32_t, const std::string &client_id, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::open_flags flags;
|
|
DECODE_OR_RETURN(request, flags);
|
|
|
|
remote::file_handle handle;
|
|
if ((ret = this->fuse_open(&path[0], flags, handle)) >= 0) {
|
|
#ifdef _WIN32
|
|
this->set_compat_client_id(handle, client_id);
|
|
#else
|
|
this->set_client_id(static_cast<native_handle>(handle), client_id);
|
|
#endif
|
|
response.encode(handle);
|
|
}
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_opendir",
|
|
[this](std::uint32_t, const std::string &client_id, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_handle handle = 0;
|
|
if ((ret = this->fuse_opendir(&path[0], handle)) >= 0) {
|
|
this->add_directory(client_id, reinterpret_cast<void *>(handle));
|
|
response.encode(handle);
|
|
}
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_read",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_size read_size;
|
|
DECODE_OR_RETURN(request, read_size);
|
|
|
|
remote::file_offset read_offset;
|
|
DECODE_OR_RETURN(request, read_offset);
|
|
|
|
remote::file_handle handle;
|
|
DECODE_OR_RETURN(request, handle);
|
|
|
|
data_buffer buffer;
|
|
if ((ret =
|
|
this->fuse_read(&path[0], reinterpret_cast<char *>(&buffer),
|
|
read_size, read_offset, handle)) > 0) {
|
|
response.encode(&buffer[0], buffer.size());
|
|
}
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_readdir",
|
|
[this](std::uint32_t, const std::string &client_id, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_offset offset;
|
|
DECODE_OR_RETURN(request, offset);
|
|
|
|
remote::file_handle handle;
|
|
DECODE_OR_RETURN(request, handle);
|
|
|
|
if (this->has_open_directory(client_id,
|
|
reinterpret_cast<void *>(handle))) {
|
|
std::string filePath;
|
|
ret = this->fuse_readdir(&path[0], offset, handle, filePath);
|
|
if (ret == 0) {
|
|
response.encode(filePath);
|
|
}
|
|
} else {
|
|
ret = -EBADF;
|
|
}
|
|
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_release",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_handle handle;
|
|
DECODE_OR_RETURN(request, handle);
|
|
|
|
return this->fuse_release(&path[0], handle);
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_releasedir",
|
|
[this](std::uint32_t, const std::string &client_id, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_handle handle;
|
|
DECODE_OR_RETURN(request, handle);
|
|
|
|
ret = this->fuse_releasedir(&path[0], handle);
|
|
if (this->remove_directory(client_id,
|
|
reinterpret_cast<void *>(handle))) {
|
|
return ret;
|
|
}
|
|
return -EBADF;
|
|
}});
|
|
/*handlerLookup_.insert({"::fuse_removexattr",
|
|
[this](std::uint32_t serviceFlags, const std::string
|
|
&client_id, std::uint64_t threadId, const std::string &method, packet
|
|
*request, packet &response) -> packet::error_type { auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
std::string name;
|
|
DECODE_OR_RETURN(request, name);
|
|
|
|
return this->fuse_removexattr(&path[0], &name[0]);
|
|
}});*/
|
|
handler_lookup_.insert(
|
|
{"::fuse_rename",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
std::int32_t ret{0};
|
|
|
|
std::string from;
|
|
DECODE_OR_RETURN(request, from);
|
|
|
|
std::string to;
|
|
DECODE_OR_RETURN(request, to);
|
|
|
|
return this->fuse_rename(from.data(), to.data());
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_rmdir",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
std::int32_t ret{0};
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
return this->fuse_rmdir(path.data());
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_setattr_x",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
std::int32_t ret{0};
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::setattr_x attr{};
|
|
DECODE_OR_RETURN(request, attr);
|
|
|
|
return this->fuse_setattr_x(path.data(), attr);
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_setbkuptime",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
std::int32_t ret{0};
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_time bkuptime{};
|
|
DECODE_OR_RETURN(request, bkuptime);
|
|
|
|
return this->fuse_setbkuptime(path.data(), bkuptime);
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_setchgtime",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
std::int32_t ret{0};
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_time chgtime{};
|
|
DECODE_OR_RETURN(request, chgtime);
|
|
|
|
return this->fuse_setchgtime(path.data(), chgtime);
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_setcrtime",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
std::int32_t ret{0};
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_time crtime{};
|
|
DECODE_OR_RETURN(request, crtime);
|
|
|
|
return this->fuse_setcrtime(path.data(), crtime);
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_setvolname",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
std::int32_t ret{0};
|
|
|
|
std::string name;
|
|
DECODE_OR_RETURN(request, name);
|
|
|
|
return this->fuse_setvolname(name.data());
|
|
}});
|
|
/*handlerLookup_.insert({"::fuse_setxattr",
|
|
[this](std::uint32_t serviceFlags, const std::string
|
|
&client_id, std::uint64_t threadId, const std::string &method, packet
|
|
*request, packet &response) -> packet::error_type { auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
std::string name;
|
|
DECODE_OR_RETURN(request, name);
|
|
|
|
remote::file_size size;
|
|
DECODE_OR_RETURN(request, size);
|
|
|
|
if (size > std::numeric_limits<std::size_t>::max())
|
|
{ return -ERANGE;
|
|
}
|
|
|
|
data_buffer value(static_cast<std::size_t>(size));
|
|
ret = request->Decode(&value[0], value.size());
|
|
if (ret == 0) {
|
|
std::int32_t flags;
|
|
DECODE_OR_RETURN(request, flags);
|
|
|
|
ret = this->fuse_setxattr(&path[0], &name[0],
|
|
&value[0], size, flags);
|
|
}
|
|
return ret;
|
|
}});
|
|
handlerLookup_.insert({"::fuse_setxattr_osx",
|
|
[this](std::uint32_t serviceFlags, const std::string
|
|
&client_id, std::uint64_t threadId, const std::string &method, packet
|
|
*request, packet &response) -> packet::error_type { auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
std::string name;
|
|
DECODE_OR_RETURN(request, name);
|
|
|
|
remote::file_size size;
|
|
DECODE_OR_RETURN(request, size);
|
|
|
|
if (size > std::numeric_limits<std::size_t>::max())
|
|
{ return -ERANGE;
|
|
}
|
|
|
|
data_buffer value(static_cast<std::size_t>(size));
|
|
ret = request->Decode(&value[0], value.size());
|
|
if (ret == 0) {
|
|
std::int32_t flags;
|
|
DECODE_OR_RETURN(request, flags);
|
|
|
|
std::uint32_t position;
|
|
DECODE_OR_RETURN(request, position);
|
|
|
|
ret = this->fuse_setxattr_osx(&path[0], &name[0],
|
|
&value[0], size, flags, position);
|
|
}
|
|
return ret;
|
|
}});*/
|
|
handler_lookup_.insert(
|
|
{"::fuse_statfs",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
std::int32_t ret{-1};
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
std::uint64_t frsize{};
|
|
DECODE_OR_RETURN(request, frsize);
|
|
|
|
remote::statfs st{};
|
|
ret = this->fuse_statfs(path.data(), frsize, st);
|
|
if (ret == 0) {
|
|
response.encode(st);
|
|
}
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_statfs_x",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
std::int32_t ret{-1};
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
std::uint64_t bsize{};
|
|
DECODE_OR_RETURN(request, bsize);
|
|
|
|
remote::statfs_x st{};
|
|
ret = this->fuse_statfs_x(path.data(), bsize, st);
|
|
if (ret == 0) {
|
|
response.encode(st);
|
|
}
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_truncate",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
std::int32_t ret{};
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_offset size{};
|
|
DECODE_OR_IGNORE(request, size);
|
|
|
|
return this->fuse_truncate(path.data(), size);
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_unlink",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
std::int32_t ret{};
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
return this->fuse_unlink(path.data());
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_utimens",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
std::int32_t ret{};
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_time tv[2] = {0};
|
|
if ((ret = request->decode(&tv[0], sizeof(remote::file_time) * 2)) ==
|
|
0) {
|
|
std::uint64_t op0{};
|
|
DECODE_OR_RETURN(request, op0);
|
|
|
|
std::uint64_t op1{};
|
|
DECODE_OR_RETURN(request, op1);
|
|
|
|
ret = this->fuse_utimens(path.data(), tv, op0, op1);
|
|
}
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_write",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
std::int32_t ret{};
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_size write_size{};
|
|
DECODE_OR_RETURN(request, write_size);
|
|
|
|
if (write_size > std::numeric_limits<std::size_t>::max()) {
|
|
return -ERANGE;
|
|
}
|
|
|
|
data_buffer buffer(write_size);
|
|
if ((ret = request->decode(buffer.data(), buffer.size())) == 0) {
|
|
remote::file_offset write_offset{};
|
|
DECODE_OR_RETURN(request, write_offset);
|
|
|
|
remote::file_handle handle{};
|
|
DECODE_OR_RETURN(request, handle);
|
|
|
|
ret = this->fuse_write(path.data(), buffer.data(), write_size,
|
|
write_offset, handle);
|
|
}
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::fuse_write_base64",
|
|
[this](std::uint32_t, const std::string &, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
std::int32_t ret{};
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_size write_size{};
|
|
DECODE_OR_RETURN(request, write_size);
|
|
|
|
if (write_size > std::numeric_limits<std::size_t>::max()) {
|
|
return -ERANGE;
|
|
}
|
|
|
|
data_buffer buffer(write_size);
|
|
if ((ret = request->decode(buffer.data(), buffer.size())) == 0) {
|
|
buffer = macaron::Base64::Decode(
|
|
std::string(buffer.begin(), buffer.end()));
|
|
write_size = buffer.size();
|
|
|
|
remote::file_offset write_offset{};
|
|
DECODE_OR_RETURN(request, write_offset);
|
|
|
|
remote::file_handle handle{};
|
|
DECODE_OR_RETURN(request, handle);
|
|
|
|
ret = this->fuse_write(path.data(), buffer.data(), write_size,
|
|
write_offset, handle);
|
|
}
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::json_create_directory_snapshot",
|
|
[this](std::uint32_t, const std::string &client_id, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
std::int32_t ret{};
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
json json_data;
|
|
json_data["handle"] = -1;
|
|
json_data["page_count"] = 0;
|
|
json_data["path"] = path;
|
|
if ((ret = this->json_create_directory_snapshot(path.data(),
|
|
json_data)) == 0) {
|
|
this->add_directory(client_id,
|
|
reinterpret_cast<void *>(
|
|
json_data["handle"].get<std::uint64_t>()));
|
|
response.encode(json_data.dump(0));
|
|
}
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::json_read_directory_snapshot",
|
|
[this](std::uint32_t, const std::string &client_id, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &response) -> packet::error_type {
|
|
std::int32_t ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_handle handle{};
|
|
DECODE_OR_RETURN(request, handle);
|
|
|
|
std::uint32_t page{};
|
|
DECODE_OR_RETURN(request, page);
|
|
|
|
ret = -EBADF;
|
|
if (this->has_open_directory(client_id,
|
|
reinterpret_cast<void *>(handle))) {
|
|
json json_data;
|
|
json_data["directory_list"] = std::vector<json>();
|
|
json_data["page"] = page;
|
|
ret = this->json_read_directory_snapshot(path, handle, page,
|
|
json_data);
|
|
if ((ret == 0) || (ret == -120)) {
|
|
response.encode(json_data.dump(0));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}});
|
|
handler_lookup_.insert(
|
|
{"::json_release_directory_snapshot",
|
|
[this](std::uint32_t, const std::string &client_id, std::uint64_t,
|
|
const std::string &, packet *request,
|
|
packet &) -> packet::error_type {
|
|
auto ret = 0;
|
|
|
|
std::string path;
|
|
DECODE_OR_RETURN(request, path);
|
|
|
|
remote::file_handle handle{};
|
|
DECODE_OR_RETURN(request, handle);
|
|
|
|
ret = this->json_release_directory_snapshot(path.data(), handle);
|
|
if (this->remove_directory(client_id,
|
|
reinterpret_cast<void *>(handle))) {
|
|
return ret;
|
|
}
|
|
return -EBADF;
|
|
}});
|
|
|
|
packet_server_ = std::make_unique<packet_server>(
|
|
config_.get_remote_port(), config_.get_remote_token(), 10,
|
|
[this](const std::string &client_id) {
|
|
return this->closed_handler(client_id);
|
|
},
|
|
[this](std::uint32_t service_flags, const std::string &client_id,
|
|
std::uint64_t thread_id, const std::string &method,
|
|
packet *request, packet &response,
|
|
packet_server::message_complete_callback message_complete) {
|
|
return this->message_handler(service_flags, client_id, thread_id,
|
|
method, request, response,
|
|
message_complete);
|
|
});
|
|
}
|
|
|
|
~remote_server_base() override {
|
|
event_system::instance().raise<service_shutdown_begin>(
|
|
"remote_server_base");
|
|
client_pool_.shutdown();
|
|
packet_server_.reset();
|
|
event_system::instance().raise<service_shutdown_end>("remote_server_base");
|
|
}
|
|
|
|
public:
|
|
using handler_callback = std::function<packet::error_type(
|
|
std::uint32_t, const std::string &, std::uint64_t, const std::string &,
|
|
packet *, packet &)>;
|
|
|
|
protected:
|
|
app_config &config_;
|
|
drive &drive_;
|
|
std::string mount_location_;
|
|
|
|
private:
|
|
client_pool client_pool_;
|
|
std::unique_ptr<packet_server> packet_server_;
|
|
std::unordered_map<std::string, handler_callback> handler_lookup_;
|
|
|
|
private:
|
|
void closed_handler(const std::string &client_id) {
|
|
client_pool_.remove_client(client_id);
|
|
close_all(client_id);
|
|
}
|
|
|
|
void
|
|
message_handler(std::uint32_t service_flags, const std::string &client_id,
|
|
std::uint64_t thread_id, const std::string &method,
|
|
packet *request, packet &response,
|
|
packet_server::message_complete_callback message_complete) {
|
|
const auto idx = method.find_last_of("::");
|
|
const auto lookup_method_name =
|
|
((idx == std::string::npos) ? "::" + method : method.substr(idx - 1));
|
|
if (handler_lookup_.find(lookup_method_name) == handler_lookup_.end()) {
|
|
message_complete(STATUS_NOT_IMPLEMENTED);
|
|
} else {
|
|
client_pool_.execute(
|
|
client_id, thread_id,
|
|
[this, lookup_method_name, service_flags, client_id, thread_id,
|
|
method, request, &response]() -> packet::error_type {
|
|
return this->handler_lookup_[lookup_method_name](
|
|
service_flags, client_id, thread_id, method, request, response);
|
|
},
|
|
message_complete);
|
|
}
|
|
}
|
|
|
|
protected:
|
|
[[nodiscard]] auto construct_api_path(std::string path) -> std::string {
|
|
path = utils::path::create_api_path(path.substr(mount_location_.size()));
|
|
return path;
|
|
}
|
|
|
|
void delete_open_directory(void *dir) override {
|
|
if (dir != nullptr) {
|
|
delete reinterpret_cast<directory_iterator *>(dir);
|
|
}
|
|
}
|
|
};
|
|
} // namespace repertory
|
|
|
|
#endif // INCLUDE_DRIVES_REMOTE_REMOTE_SERVER_BASE_HPP_
|