1 Commits

Author SHA1 Message Date
8dd46b8ad8 v2.0.2-rc (#27)
Some checks reported errors
BlockStorage/repertory/pipeline/head Something is wrong with the build of this commit
## v2.0.2-rc

### BREAKING CHANGES

* Refactored `config.json` - will need to verify configuration settings prior to mounting

### Issues

* \#12 \[Unit Test\] Complete all providers unit tests
* \#14 \[Unit Test\] SQLite mini-ORM unit tests and cleanup
* \#16 Add support for bucket name in Sia provider
* \#17 Update to common c++ build system
  * A single 64-bit Linux Jenkins server is used to build all Linux and Windows versions
  * All dependency sources are now included
  * MSVC is no longer supported
  * MSYS2 is required for building Windows binaries on Windows
  * OS X support is temporarily disabled
* \#19 \[bug\] Rename file is broken for files that are existing
* \#23 \[bug\] Incorrect file size displayed while upload is pending
* \#24 RocksDB implementations should be transactional
* \#25 Writes should block when maximum cache size is reached
* \#26 Complete ring buffer and direct download support

### Changes from v2.0.1-rc

* Ability to choose between RocksDB and SQLite databases
* Added direct reads and implemented download fallback
* Corrected file times on S3 and Sia providers
* Corrected handling of `chown()` and `chmod()`
* Fixed erroneous download of chunks after resize

Reviewed-on: #27
2024-12-28 15:56:40 -06:00
253 changed files with 26465 additions and 17560 deletions

View File

@ -23,6 +23,7 @@ cppflags
cpphttplib cpphttplib
cpptrace cpptrace
cppvsdbg cppvsdbg
create_notraverse
crypto_aead_xchacha20poly1305_ietf_npubbytes crypto_aead_xchacha20poly1305_ietf_npubbytes
cstdint cstdint
cxxflags cxxflags
@ -30,6 +31,7 @@ cxxstd
d_largefile64_source d_largefile64_source
d_largefile_source d_largefile_source
d_ndebug d_ndebug
dacl_security_information
dbackward_shared dbackward_shared
dbghelp dbghelp
dboost_root dboost_root
@ -94,6 +96,7 @@ expect_streq
fallocate_impl fallocate_impl
fext fext
fgetattr fgetattr
fgetattr_impl
filebase filebase
flac_version flac_version
flag_nopath flag_nopath
@ -117,6 +120,7 @@ icui18n
icuuc icuuc
iostreams iostreams
iphlpapi iphlpapi
jthread
libbitcoin libbitcoin
libbitcoinsystem libbitcoinsystem
libcurl libcurl
@ -135,6 +139,8 @@ libuuid
libuuid_include_dirs libuuid_include_dirs
libvlc libvlc
linkflags linkflags
lptr
lpwstr
markdownlint markdownlint
mbig mbig
msvc msvc
@ -153,7 +159,9 @@ oleaut32
openal_version openal_version
openssldir openssldir
pkgconfig pkgconfig
plarge_integer
plex plex
println
project_enable_fontconfig project_enable_fontconfig
project_enable_gtkmm project_enable_gtkmm
project_enable_libdsm project_enable_libdsm
@ -165,11 +173,15 @@ pugixml_project
puint32 puint32
pvoid pvoid
pwstr pwstr
rdrw
remote_winfsp remote_winfsp
renterd renterd
richtext richtext
rocksdb_library rocksdb_library
rpcrt4 rpcrt4
s_igid
s_isvtx
s_iuid
sddl_revision_1 sddl_revision_1
secp256k1 secp256k1
secur32 secur32
@ -218,4 +230,4 @@ wsign-conversion
wunused wunused
wuseless wuseless
wxwidgets_version wxwidgets_version
xattr xattr

View File

@ -6,7 +6,7 @@ pipeline {
environment { environment {
DEVELOPER_PRIVATE_KEY = "/.ci/repertory/cert/developer.priv" DEVELOPER_PRIVATE_KEY = "/.ci/repertory/cert/developer.priv"
DEVELOPER_PUBLIC_KEY = "/.ci/repertory/cert/developer.pub" DEVELOPER_PUBLIC_KEY = "/.ci/repertory/cert/developer.pub"
PROJECT_TEST_DIR = "/.ci/repertory/test" PROJECT_TEST_CONFIG_DIR = "/.ci/repertory/test_config"
} }
options { options {

View File

@ -18,14 +18,14 @@ if vim.env.NV_DARCULA_ENABLE_DAP then
local externalConsole = gos.is_windows local externalConsole = gos.is_windows
local type = "cppdbg" local type = "cppdbg"
local cwd = gpath.create_path("./build") local cwd = gpath.create_path("./dist/debug/shared/linux/x86_64/repertory/")
dap.configurations.cpp = { dap.configurations.cpp = {
{ {
name = "Mount", name = "Mount",
type = type, type = type,
request = "launch", request = "launch",
program = function() program = function()
return gpath.create_path(cwd, "repertory") return gpath.create_path(cwd, "bin/repertory")
end, end,
cwd = cwd, cwd = cwd,
stopAtEntry = true, stopAtEntry = true,
@ -36,8 +36,9 @@ if vim.env.NV_DARCULA_ENABLE_DAP then
type = type, type = type,
request = "launch", request = "launch",
program = function() program = function()
return gpath.create_path(cwd, "repertory_tests") return gpath.create_path(cwd, "bin/repertory_test")
end, end,
args={"--gtest_filter=utils_db*"},
cwd = cwd, cwd = cwd,
stopAtEntry = true, stopAtEntry = true,
externalConsole=externalConsole, externalConsole=externalConsole,

View File

@ -2,22 +2,34 @@
## v2.0.2-rc ## v2.0.2-rc
### BREAKING CHANGES
* Refactored `config.json` - will need to verify configuration settings prior to mounting
### Issues ### Issues
* \#12 \[Unit Test\] Complete all providers unit tests * \#12 \[Unit Test\] Complete all providers unit tests
* \#14 \[Unit Test \] SQLite mini-ORM unit tests and cleanup * \#14 \[Unit Test\] SQLite mini-ORM unit tests and cleanup
* \#16 Add support for bucket name in Sia provider * \#16 Add support for bucket name in Sia provider
* \#17 Update to common c++ build system * \#17 Update to common c++ build system
* A single 64-bit Linux Jenkins server is used to build all Linux and Windows versions * A single 64-bit Linux Jenkins server is used to build all Linux and Windows versions
* All dependency sources are now included * All dependency sources are now included
* MSVC is no longer supported * MSVC is no longer supported
* MSYS2 is required for building Windows binaries Windows * MSYS2 is required for building Windows binaries on Windows
* OS X support is temporarily disabled * OS X support is temporarily disabled
* \#19 \[bug\] Rename file is broken for files that are existing * \#19 \[bug\] Rename file is broken for files that are existing
* \#23 \[bug\] Incorrect file size displayed while upload is pending
* \#24 RocksDB implementations should be transactional
* \#25 Writes should block when maximum cache size is reached
* \#26 Complete ring buffer and direct download support
### Changes from v2.0.1-rc ### Changes from v2.0.1-rc
* Ability to choose between RocksDB and SQLite databases
* Added direct reads and implemented download fallback
* Corrected file times on S3 and Sia providers * Corrected file times on S3 and Sia providers
* Corrected handling of `chown()` and `chmod()`
* Fixed erroneous download of chunks after resize
## v2.0.1-rc ## v2.0.1-rc

View File

@ -148,6 +148,7 @@ endif()
-DPROJECT_ENABLE_LIBSODIUM=${PROJECT_ENABLE_LIBSODIUM} -DPROJECT_ENABLE_LIBSODIUM=${PROJECT_ENABLE_LIBSODIUM}
-DPROJECT_ENABLE_OPENSSL=${PROJECT_ENABLE_OPENSSL} -DPROJECT_ENABLE_OPENSSL=${PROJECT_ENABLE_OPENSSL}
-DPROJECT_ENABLE_PUGIXML=${PROJECT_ENABLE_PUGIXML} -DPROJECT_ENABLE_PUGIXML=${PROJECT_ENABLE_PUGIXML}
-DPROJECT_ENABLE_ROCKSDB=${PROJECT_ENABLE_ROCKSDB}
-DPROJECT_ENABLE_SPDLOG=${PROJECT_ENABLE_SPDLOG} -DPROJECT_ENABLE_SPDLOG=${PROJECT_ENABLE_SPDLOG}
-DPROJECT_ENABLE_SQLITE=${PROJECT_ENABLE_SQLITE} -DPROJECT_ENABLE_SQLITE=${PROJECT_ENABLE_SQLITE}
-DPROJECT_ENABLE_STDUUID=${PROJECT_ENABLE_STDUUID} -DPROJECT_ENABLE_STDUUID=${PROJECT_ENABLE_STDUUID}

View File

@ -7,7 +7,6 @@ on Windows.
* Optimized for [Plex Media Server](https://www.plex.tv/) * Optimized for [Plex Media Server](https://www.plex.tv/)
* Single application to mount AWS S3 and/or Sia * Single application to mount AWS S3 and/or Sia
* Only 1 Sia mount and 1 S3 mount (per bucket) per user is supported.
* Remote mounting of Repertory instances on Linux ~~, OS X~~ and Windows * Remote mounting of Repertory instances on Linux ~~, OS X~~ and Windows
* Securely share your mounts over TCP/IP (`XChaCha20-Poly1305` stream cipher) * Securely share your mounts over TCP/IP (`XChaCha20-Poly1305` stream cipher)
* Cross-platform support (Linux 64-bit, Linux arm64/aarch64, ~~OS X,~~ Windows 64-bit) * Cross-platform support (Linux 64-bit, Linux arm64/aarch64, ~~OS X,~~ Windows 64-bit)
@ -29,26 +28,69 @@ on Windows.
* ~~OS X Mojave and above~~ * ~~OS X Mojave and above~~
* Windows 64-bit 10, 11 * Windows 64-bit 10, 11
## Usage
### Notable Options
* `-dc`
* Display mount configuration.
* For Sia, `--name` is optional
* For S3, the `-s3` option is required along with `--name`
* `--help`
* Display all mount utility options.
* `--name, -na [name]`
* The `--name` option can be set to any valid value allowed as a file name for your filesystem.
* For Sia, the bucket name will be set to the same value if it is empty in the configuration file.
* If the `--name` option is not specified, `default` will be used.
* For S3, the `--name` option is required and does not affect the bucket name.
* `-set SiaConfig.Bucket`
* Set Sia bucket name for the mount.
* Can be used in combination with `--name` to target a unique configuration.
* `-set S3Config.Bucket`
* S3 bucket name for the mount.
* Must be used in combination with `--name` to target a unique configuration.
* Must be used in combination with `-s3`.
### Sia
* Linux
* `repertory /mnt/location`
* `repertory --name default /mnt/location`
* Windows
* `repertory.exe t:`
* `repertory.exe --name default t:`
### S3
* Linux
* `repertory --name storj -s3 /mnt/location`
* Windows
* `repertory.exe --name storj -s3 t:`
## Compiling ## Compiling
* Successful compilation will result in all required files being placed in the `dist/` directory * Successful compilation will result in all required files being placed in the `dist/` directory
* Linux * Linux
* Ensure `docker` is installed * Ensure `docker` is installed
* For x86_64: * For x86_64:
* Release: `scripts/make_unix.sh x86_64` * RelWithDebInfo: `scripts/make_unix.sh`
* Debug: `scripts/make_unix.sh x86_64 debug` * Release: `scripts/make_unix.sh x86_64 Release`
* Debug: `scripts/make_unix.sh x86_64 Debug`
* For aarch64: * For aarch64:
* Release: `scripts/make_unix.sh aarch64` * RelWithDebInfo: `scripts/make_unix.sh aarch64`
* Debug: `scripts/make_unix.sh aarch64 debug` * Release: `scripts/make_unix.sh aarch64 Release`
* Debug: `scripts/make_unix.sh aarch64 Debug`
* Windows * Windows
* RECOMMENDED: Cross-compiling on Linux * OFFICIAL: Cross-compiling on Linux
* Ensure `docker` is installed * Ensure `docker` is installed
* Release: `scripts/make_win32.sh` * RelWithDebInfo: `scripts/make_win32.sh`
* Debug: `scripts/make_win32.sh debug` * Release: `scripts/make_win32.sh x86_64 Release`
* Compiling on Windows * Debug: `scripts/make_win32.sh x86_64 Debug`
* UNOFFICIAL: Compiling on Windows
* Ensure latest [MSYS2](https://www.msys2.org/) is installed * Ensure latest [MSYS2](https://www.msys2.org/) is installed
* Release: `scripts/make_win32.cmd` * RelWithDebInfo: `scripts\make_win32.cmd`
* Debug: `scripts/make_win32.cmd debug` * Release: `scripts\make_win32.cmd x86_64 Release`
* Debug: `scripts\make_win32.cmd x86_64 Debug`
## Credits ## Credits

View File

@ -1,41 +1,20 @@
set(BINUTILS_HASH ae9a5789e23459e59606e6714723f2d3ffc31c03174191ef0d015bdf06007450) set(BINUTILS_HASH ae9a5789e23459e59606e6714723f2d3ffc31c03174191ef0d015bdf06007450)
set(BOOST_HASH f55c340aa49763b1925ccf02b2e83f35fdcf634c9d5164a2acb87540173c741d)
set(BOOST2_HASH 7bd7ddceec1a1dfdcbdb3e609b60d01739c38390a5f956385a12f3122049f0ca) set(BOOST2_HASH 7bd7ddceec1a1dfdcbdb3e609b60d01739c38390a5f956385a12f3122049f0ca)
set(BOOST_HASH be0d91732d5b0cc6fbb275c7939974457e79b54d6f07ce2e3dfdd68bef883b0b) set(CPP_HTTPLIB_HASH 405abd8170f2a446fc8612ac635d0db5947c0d2e156e32603403a4496255ff00)
set(CLI11_HASH f2d893a65c3b1324c50d4e682c0cdc021dd0477ae2c048544f39eed6654b699a) set(CURL_HASH 5a231145114589491fc52da118f9c7ef8abee885d1cb1ced99c7290e9a352f07)
set(CPP_HTTPLIB_HASH c1742fc7179aaae2a67ad9bba0740b7e9ffaf4f5e62feef53101ecdef1478716) set(EXPAT_HASH 372b18f6527d162fa9658f1c74d22a37429b82d822f5a1e1fc7e00f6045a06a2)
set(CURL_HASH d714818f6ac41ae9154850158fed44b7a87650a6d52f83d3bcb9aa527be354d7)
set(CXXOPTS_HASH 841f49f2e045b9c6365997c2a8fbf76e6f215042dda4511a5bb04bc5ebc7f88a)
set(EXPAT_HASH fbd032683370d761ba68dba2566d3280a154f5290634172d60a79b24d366d9dc)
set(FLAC_HASH 0a4bb82a30609b606650d538a804a7b40205366ce8fc98871b0ecf3fbb0611ee)
set(FMT_HASH 6cb1e6d37bdcb756dbbe59be438790db409cdb4868c66e888d5df9f13f7c027f)
set(FONTCONFIG_HASH f5f359d6332861bd497570848fcb42520964a9e83d5e3abe397b6b6db9bcaaf4)
set(FREETYPE2_HASH 5c3a8e78f7b24c20b25b54ee575d6daa40007a5f4eea2845861c3409b3021747)
set(GCC_HASH 7d376d445f93126dc545e2c0086d0f647c3094aae081cdb78f42ce2bc25e7293) set(GCC_HASH 7d376d445f93126dc545e2c0086d0f647c3094aae081cdb78f42ce2bc25e7293)
set(GTEST_HASH 7b42b4d6ed48810c5362c265a17faebe90dc2373c885e5216439d37927f02926) set(GTEST_HASH 7b42b4d6ed48810c5362c265a17faebe90dc2373c885e5216439d37927f02926)
set(ICU_HASH 925e6b4b8cf8856e0ac214f6f34e30dee63b7bb7a50460ab4603950eff48f89e) set(ICU_HASH 925e6b4b8cf8856e0ac214f6f34e30dee63b7bb7a50460ab4603950eff48f89e)
set(JSON_HASH 0d8ef5af7f9794e3263480193c491549b2ba6cc74bb018906202ada498a79406) set(JSON_HASH 0d8ef5af7f9794e3263480193c491549b2ba6cc74bb018906202ada498a79406)
set(LIBDSM_HASH 747c4563d6291303d9b085c9e7dc96ac44f91871dcac3e20480fdcc066eee88a)
set(LIBEVENT_HASH 7180a979aaa7000e1264da484f712d403fcf7679b1e9212c4e3d09f5c93efc24)
set(LIBICONV_HASH 8f74213b56238c85a50a5329f77e06198771e70dd9a739779f4c02f65d971313)
set(LIBJPEG_TURBO_HASH a649205a90e39a548863a3614a9576a3fb4465f8e8e66d54999f127957c25b21)
set(LIBPNG_HASH fecc95b46cf05e8e3fc8a414750e0ba5aad00d89e9fdf175e94ff041caf1a03a)
set(LIBSODIUM_HASH 8e5aeca07a723a27bbecc3beef14b0068d37e7fc0e97f51b3f1c82d2a58005c1) set(LIBSODIUM_HASH 8e5aeca07a723a27bbecc3beef14b0068d37e7fc0e97f51b3f1c82d2a58005c1)
set(LIBTASN_HASH 1613f0ac1cf484d6ec0ce3b8c06d56263cc7242f1c23b30d82d23de345a63f7a)
set(MINGW_HASH 3f66bce069ee8bed7439a1a13da7cb91a5e67ea6170f21317ac7f5794625ee10) set(MINGW_HASH 3f66bce069ee8bed7439a1a13da7cb91a5e67ea6170f21317ac7f5794625ee10)
set(NANA_HASH 56f7b1ed006c750fccf8ef15ab1e83f96751f2dfdcb68d93e5f712a6c9b58bcb) set(OPENSSL_HASH e15dda82fe2fe8139dc2ac21a36d4ca01d5313c75f99f46c4e8a27709b7294bf)
set(NUSPELL_HASH 5d4baa1daf833a18dc06ae0af0571d9574cc849d47daff6b9ce11dac0a5ded6a)
set(OGG_HASH 0eb4b4b9420a0f51db142ba3f9c64b333f826532dc0f48c6410ae51f4799b664)
set(OPENAL_HASH dfddf3a1f61059853c625b7bb03de8433b455f2f79f89548cbcbd5edca3d4a4a)
set(OPENSSL_HASH 777cd596284c883375a2a7a11bf5d2786fc5413255efab20c50d6ffe6d020b7e)
set(PKG_CONFIG_HASH 6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591) set(PKG_CONFIG_HASH 6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591)
set(PUGIXML_HASH 2f10e276870c64b1db6809050a75e11a897a8d7456c4be5c6b2e35a11168a015) set(PUGIXML_HASH 2f10e276870c64b1db6809050a75e11a897a8d7456c4be5c6b2e35a11168a015)
set(ROCKSDB_HASH b20780586d3df4a3c5bcbde341a2c1946b03d18237960bda5bc5e9538f42af40) set(ROCKSDB_HASH 9b810c81731835fda0d4bbdb51d3199d901fa4395733ab63752d297da84c5a47)
set(SDL_HASH 254a767aa486fa6308d4473159c1f23c794610be775d63e98084111d96814b85) set(SPDLOG_HASH 9962648c9b4f1a7bbc76fd8d9172555bad1871fdb14ff4f842ef87949682caa5)
set(SECP256K1_HASH 61583939f1f25b92e6401e5b819e399da02562de663873df3056993b40148701)
set(SFML_HASH 82535db9e57105d4f3a8aedabd138631defaedc593cab589c924b7d7a11ffb9d)
set(SPDLOG_HASH 1586508029a7d0670dfcb2d97575dcdc242d3868a259742b69f100801ab4e16b)
set(SQLITE_HASH 77823cb110929c2bcb0f5d48e4833b5c59a8a6e40cdea3936b99e199dbbe5784) set(SQLITE_HASH 77823cb110929c2bcb0f5d48e4833b5c59a8a6e40cdea3936b99e199dbbe5784)
set(STDUUID_HASH b1176597e789531c38481acbbed2a6894ad419aab0979c10410d59eb0ebf40d3) set(STDUUID_HASH b1176597e789531c38481acbbed2a6894ad419aab0979c10410d59eb0ebf40d3)
set(VORBIS_HASH 270c76933d0934e42c5ee0a54a36280e2d87af1de3cc3e584806357e237afd13)
set(WXWIDGETS_HASH 0ad86a3ad3e2e519b6a705248fc9226e3a09bbf069c6c692a02acf7c2d1c6b51)
set(ZLIB_HASH 17e88863f3600672ab49182f217281b6fc4d3c762bde361935e436a95214d05c) set(ZLIB_HASH 17e88863f3600672ab49182f217281b6fc4d3c762bde361935e436a95214d05c)

View File

@ -17,6 +17,7 @@ include(cmake/libraries/fuse.cmake)
include(cmake/libraries/json.cmake) include(cmake/libraries/json.cmake)
include(cmake/libraries/libsodium.cmake) include(cmake/libraries/libsodium.cmake)
include(cmake/libraries/pugixml.cmake) include(cmake/libraries/pugixml.cmake)
include(cmake/libraries/rocksdb.cmake)
include(cmake/libraries/spdlog.cmake) include(cmake/libraries/spdlog.cmake)
include(cmake/libraries/sqlite.cmake) include(cmake/libraries/sqlite.cmake)
include(cmake/libraries/stduuid.cmake) include(cmake/libraries/stduuid.cmake)

View File

@ -0,0 +1,34 @@
if(PROJECT_ENABLE_ROCKSDB)
if(PROJECT_BUILD)
add_definitions(-DPROJECT_ENABLE_ROCKSDB)
find_library(ROCKSDB_LIBRARY NAMES librocksdb.a REQUIRED)
link_libraries(${ROCKSDB_LIBRARY})
elseif(NOT PROJECT_IS_MINGW OR CMAKE_HOST_WIN32)
ExternalProject_Add(rocksdb_project
PREFIX external
URL ${PROJECT_3RD_PARTY_DIR}/rocksdb-${ROCKSDB_VERSION}.tar.gz
URL_HASH SHA256=${ROCKSDB_HASH}
LIST_SEPARATOR |
CMAKE_ARGS ${PROJECT_EXTERNAL_CMAKE_FLAGS}
-DBUILD_SHARED_LIBS=OFF
-DBUILD_STATIC_LIBS=ON
-DFAIL_ON_WARNINGS=OFF
-DPORTABLE=1
-DROCKSDB_BUILD_SHARED=OFF
-DROCKSDB_INSTALL_ON_WINDOWS=ON
-DWITH_BENCHMARK=OFF
-DWITH_BENCHMARK_TOOLS=OFF
-DWITH_CORE_TOOLS=OFF
-DWITH_EXAMPLES=OFF
-DWITH_GFLAGS=OFF
-DWITH_IOSTATS_CONTEXT=OFF
-DWITH_PERF_CONTEXT=OFF
-DWITH_TESTS=OFF
-DWITH_TOOLS=OFF
-DWITH_TRACE_TOOLS=OFF
-DWITH_ZLIB=ON
)
list(APPEND PROJECT_DEPENDENCIES rocksdb_project)
endif()
endif()

View File

@ -6,6 +6,7 @@ option(PROJECT_ENABLE_JSON "Enable JSON for Modern C++ library" ON)
option(PROJECT_ENABLE_LIBSODIUM "Enable libsodium library" ON) option(PROJECT_ENABLE_LIBSODIUM "Enable libsodium library" ON)
option(PROJECT_ENABLE_OPENSSL "Enable OpenSSL library" ON) option(PROJECT_ENABLE_OPENSSL "Enable OpenSSL library" ON)
option(PROJECT_ENABLE_PUGIXML "Enable PugiXML library" ON) option(PROJECT_ENABLE_PUGIXML "Enable PugiXML library" ON)
option(PROJECT_ENABLE_ROCKSDB "Enable RocksDB library" ON)
option(PROJECT_ENABLE_SPDLOG "Enable spdlog library" ON) option(PROJECT_ENABLE_SPDLOG "Enable spdlog library" ON)
option(PROJECT_ENABLE_SQLITE "Enable SQLite" ON) option(PROJECT_ENABLE_SQLITE "Enable SQLite" ON)
option(PROJECT_ENABLE_STDUUID "Enable stduuid library" ON) option(PROJECT_ENABLE_STDUUID "Enable stduuid library" ON)

View File

@ -1,15 +1,15 @@
set(BINUTILS_VERSION 2.41) set(BINUTILS_VERSION 2.41)
set(BOOST_MAJOR_VERSION 1)
set(BOOST_MINOR_VERSION 85)
set(BOOST_PATCH_VERSION 0)
set(BOOST2_MAJOR_VERSION 1) set(BOOST2_MAJOR_VERSION 1)
set(BOOST2_MINOR_VERSION 76) set(BOOST2_MINOR_VERSION 76)
set(BOOST2_PATCH_VERSION 0) set(BOOST2_PATCH_VERSION 0)
set(CPP_HTTPLIB_VERSION 0.16.3) set(BOOST_MAJOR_VERSION 1)
set(CURL_VERSION 8.9.1) set(BOOST_MINOR_VERSION 87)
set(CURL2_VERSION 8_9_1) set(BOOST_PATCH_VERSION 0)
set(EXPAT_VERSION 2.6.2) set(CPP_HTTPLIB_VERSION 0.18.1)
set(EXPAT2_VERSION 2_6_2) set(CURL2_VERSION 8_11_0)
set(CURL_VERSION 8.11.0)
set(EXPAT2_VERSION 2_6_4)
set(EXPAT_VERSION 2.6.4)
set(GCC_VERSION 14.2.0) set(GCC_VERSION 14.2.0)
set(GTEST_VERSION 1.15.2) set(GTEST_VERSION 1.15.2)
set(ICU_VERSION 75-1) set(ICU_VERSION 75-1)
@ -17,11 +17,12 @@ set(JSON_VERSION 3.11.3)
set(LIBSODIUM_VERSION 1.0.20) set(LIBSODIUM_VERSION 1.0.20)
set(MESA_VERSION 23.3.3) set(MESA_VERSION 23.3.3)
set(MINGW_VERSION 11.0.1) set(MINGW_VERSION 11.0.1)
set(OPENSSL_VERSION 3.3.1) set(OPENSSL_VERSION 3.4.0)
set(PKG_CONFIG_VERSION 0.29.2) set(PKG_CONFIG_VERSION 0.29.2)
set(PUGIXML_VERSION 1.14) set(PUGIXML_VERSION 1.14)
set(SPDLOG_VERSION 1.14.1) set(ROCKSDB_VERSION 9.7.4)
set(SQLITE_VERSION 3460100) set(SPDLOG_VERSION 1.15.0)
set(SQLITE2_VERSION 3.46.1) set(SQLITE2_VERSION 3.46.1)
set(SQLITE_VERSION 3460100)
set(STDUUID_VERSION 1.2.3) set(STDUUID_VERSION 1.2.3)
set(ZLIB_VERSION 1.3.1) set(ZLIB_VERSION 1.3.1)

View File

@ -30,6 +30,7 @@ PROJECT_ENABLE_JSON=ON
PROJECT_ENABLE_LIBSODIUM=ON PROJECT_ENABLE_LIBSODIUM=ON
PROJECT_ENABLE_OPENSSL=ON PROJECT_ENABLE_OPENSSL=ON
PROJECT_ENABLE_PUGIXML=ON PROJECT_ENABLE_PUGIXML=ON
PROJECT_ENABLE_ROCKSDB=ON
PROJECT_ENABLE_SPDLOG=ON PROJECT_ENABLE_SPDLOG=ON
PROJECT_ENABLE_SQLITE=ON PROJECT_ENABLE_SQLITE=ON
PROJECT_ENABLE_STDUUID=ON PROJECT_ENABLE_STDUUID=ON

View File

@ -572,8 +572,8 @@ RUN if [ -f "/3rd_party/flac-${MY_FLAC_VERSION}.tar.gz" ]; then \
&& cd build \ && cd build \
&& cmake .. \ && cmake .. \
-DBUILD_DOCS=OFF \ -DBUILD_DOCS=OFF \
-DBUILD_EXAMPLES=ON \ -DBUILD_EXAMPLES=OFF \
-DBUILD_PROGRAMS=ON \ -DBUILD_PROGRAMS=OFF \
-DBUILD_SHARED_LIBS=ON \ -DBUILD_SHARED_LIBS=ON \
-DBUILD_STATIC_LIBS=ON \ -DBUILD_STATIC_LIBS=ON \
-DBUILD_TESTING=OFF \ -DBUILD_TESTING=OFF \
@ -604,6 +604,7 @@ RUN if [ -f "/3rd_party/SFML-${MY_SFML_VERSION}.tar.gz" ]; then \
-DBUILD_STATIC_LIBS=ON \ -DBUILD_STATIC_LIBS=ON \
-DCMAKE_CXX_STANDARD=${MY_CXX_STANDARD} \ -DCMAKE_CXX_STANDARD=${MY_CXX_STANDARD} \
-DCMAKE_INSTALL_PREFIX=${MY_MINGW_DIR} \ -DCMAKE_INSTALL_PREFIX=${MY_MINGW_DIR} \
-DCMAKE_SYSTEM_PROCESSOR=AMD64 \
-DCMAKE_TOOLCHAIN_FILE=${MY_TOOLCHAIN_FILE_CMAKE} \ -DCMAKE_TOOLCHAIN_FILE=${MY_TOOLCHAIN_FILE_CMAKE} \
&& make -j${MY_NUM_JOBS} \ && make -j${MY_NUM_JOBS} \
&& make install \ && make install \

View File

@ -3,8 +3,8 @@
CURRENT_DIR=$(dirname "$0") CURRENT_DIR=$(dirname "$0")
CURRENT_DIR=$(realpath ${CURRENT_DIR}) CURRENT_DIR=$(realpath ${CURRENT_DIR})
rsync -av --progress ${CURRENT_DIR}/${PROJECT_NAME}/${PROJECT_NAME}_test/test_config/ \ rsync -av --progress ${CURRENT_DIR}/${PROJECT_NAME}/${PROJECT_NAME}_test/test_input/ \
${PROJECT_BUILD_DIR}/build/test_config/ ${PROJECT_BUILD_DIR}/build/test_input/
rsync -av --progress ${CURRENT_DIR}/${PROJECT_NAME}/${PROJECT_NAME}_test/test_config/ \ rsync -av --progress ${CURRENT_DIR}/${PROJECT_NAME}/${PROJECT_NAME}_test/test_input/ \
${PROJECT_DIST_DIR}/test_config/ ${PROJECT_DIST_DIR}/test_input/

View File

@ -22,10 +22,9 @@
#ifndef REPERTORY_INCLUDE_APP_CONFIG_HPP_ #ifndef REPERTORY_INCLUDE_APP_CONFIG_HPP_
#define REPERTORY_INCLUDE_APP_CONFIG_HPP_ #define REPERTORY_INCLUDE_APP_CONFIG_HPP_
#include "events/event_system.hpp" #include "events/event.hpp"
#include "events/events.hpp" #include "types/remote.hpp"
#include "types/repertory.hpp" #include "types/repertory.hpp"
#include "utils/error_utils.hpp"
namespace repertory { namespace repertory {
class app_config final { class app_config final {
@ -40,7 +39,7 @@ public:
default_data_directory(const provider_type &prov) -> std::string; default_data_directory(const provider_type &prov) -> std::string;
[[nodiscard]] static auto [[nodiscard]] static auto
default_remote_port(const provider_type &prov) -> std::uint16_t; default_remote_api_port(const provider_type &prov) -> std::uint16_t;
[[nodiscard]] static auto [[nodiscard]] static auto
default_rpc_port(const provider_type &prov) -> std::uint16_t; default_rpc_port(const provider_type &prov) -> std::uint16_t;
@ -54,401 +53,202 @@ public:
public: public:
app_config(const provider_type &prov, std::string_view data_directory = ""); app_config(const provider_type &prov, std::string_view data_directory = "");
app_config() = delete;
app_config(app_config &&) = delete;
app_config(const app_config &) = delete;
~app_config() { save(); } ~app_config() { save(); }
auto operator=(const app_config &) -> app_config & = delete;
auto operator=(app_config &&) -> app_config & = delete;
private: private:
provider_type prov_; provider_type prov_;
std::string api_auth_; atomic<std::string> api_auth_;
std::uint16_t api_port_; std::atomic<std::uint16_t> api_port_;
std::string api_user_; atomic<std::string> api_user_;
bool config_changed_; std::atomic<bool> config_changed_;
std::string data_directory_; std::atomic<database_type> db_type_{database_type::rocksdb};
std::uint8_t download_timeout_secs_; std::atomic<std::uint8_t> download_timeout_secs_;
bool enable_chunk_downloader_timeout_; std::atomic<bool> enable_download_timeout_;
bool enable_comm_duration_events_; std::atomic<bool> enable_drive_events_;
bool enable_drive_events_;
bool enable_max_cache_size_;
#if defined(_WIN32) #if defined(_WIN32)
bool enable_mount_manager_; std::atomic<bool> enable_mount_manager_;
#endif #endif // defined(_WIN32)
bool enable_remote_mount_; std::atomic<event_level> event_level_;
encrypt_config encrypt_config_; std::atomic<std::uint32_t> eviction_delay_mins_;
event_level event_level_; std::atomic<bool> eviction_uses_accessed_time_;
std::uint32_t eviction_delay_mins_; std::atomic<std::uint16_t> high_freq_interval_secs_;
bool eviction_uses_accessed_time_; std::atomic<std::uint16_t> low_freq_interval_secs_;
std::uint8_t high_freq_interval_secs_; std::atomic<std::uint64_t> max_cache_size_bytes_;
bool is_remote_mount_; std::atomic<std::uint8_t> max_upload_count_;
std::uint32_t low_freq_interval_secs_; std::atomic<std::uint16_t> med_freq_interval_secs_;
std::uint64_t max_cache_size_bytes_; std::atomic<std::uint16_t> online_check_retry_secs_;
std::uint8_t max_upload_count_; std::atomic<std::uint16_t> orphaned_file_retention_days_;
std::uint8_t min_download_timeout_secs_; std::atomic<download_type> preferred_download_type_;
std::uint16_t online_check_retry_secs_; std::atomic<std::uint16_t> retry_read_count_;
std::uint16_t orphaned_file_retention_days_; std::atomic<std::uint16_t> ring_buffer_file_size_;
std::string preferred_download_type_; std::atomic<std::uint16_t> task_wait_ms_;
std::uint8_t read_ahead_count_;
std::uint8_t remote_client_pool_size_; private:
std::string remote_host_name_or_ip_;
std::uint8_t remote_max_connections_;
std::uint16_t remote_port_;
std::uint16_t remote_receive_timeout_secs_;
std::uint16_t remote_send_timeout_secs_;
std::string remote_token_;
std::uint16_t retry_read_count_;
std::uint16_t ring_buffer_file_size_;
std::string cache_directory_; std::string cache_directory_;
host_config hc_; std::string data_directory_;
s3_config s3_config_; atomic<encrypt_config> encrypt_config_;
sia_config sia_config_{"default"}; atomic<host_config> host_config_;
std::uint64_t version_{REPERTORY_CONFIG_VERSION};
std::string log_directory_; std::string log_directory_;
mutable std::recursive_mutex read_write_mutex_; mutable std::recursive_mutex read_write_mutex_;
mutable std::recursive_mutex remote_mount_mutex_; atomic<remote::remote_config> remote_config_;
atomic<remote::remote_mount> remote_mount_;
atomic<s3_config> s3_config_;
atomic<sia_config> sia_config_;
std::unordered_map<std::string, std::function<std::string()>>
value_get_lookup_;
std::unordered_map<std::string,
std::function<std::string(const std::string &)>>
value_set_lookup_;
std::uint64_t version_{REPERTORY_CONFIG_VERSION};
private: private:
[[nodiscard]] auto load() -> bool; [[nodiscard]] auto load() -> bool;
template <typename dest>
auto get_value(const json &json_document, const std::string &name, dest &dst,
bool &success_flag) -> bool {
constexpr const auto *function_name =
static_cast<const char *>(__FUNCTION__);
auto ret = false;
try {
if (json_document.find(name) != json_document.end()) {
dst = json_document[name].get<dest>();
ret = true;
} else {
success_flag = false;
}
} catch (const json::exception &ex) {
utils::error::raise_error(function_name, ex, "exception occurred");
success_flag = false;
ret = false;
}
return ret;
}
template <typename dest, typename source> template <typename dest, typename source>
auto set_value(dest &dst, const source &src) -> bool { auto set_value(dest &dst, const source &src) -> bool;
auto ret = false;
recur_mutex_lock lock(read_write_mutex_);
if (dst != src) {
dst = src;
config_changed_ = true;
save();
ret = true;
}
return ret;
}
public: public:
[[nodiscard]] auto get_api_auth() const -> std::string { return api_auth_; } [[nodiscard]] auto get_api_auth() const -> std::string;
[[nodiscard]] auto get_api_port() const -> std::uint16_t { return api_port_; } [[nodiscard]] auto get_api_port() const -> std::uint16_t;
[[nodiscard]] auto get_api_user() const -> std::string { return api_user_; } [[nodiscard]] auto get_api_user() const -> std::string;
[[nodiscard]] auto get_cache_directory() const -> std::string { [[nodiscard]] auto get_cache_directory() const -> std::string;
return cache_directory_;
}
[[nodiscard]] auto get_chunk_downloader_timeout_secs() const -> std::uint8_t {
return std::max(min_download_timeout_secs_, download_timeout_secs_);
}
[[nodiscard]] auto get_config_file_path() const -> std::string; [[nodiscard]] auto get_config_file_path() const -> std::string;
[[nodiscard]] auto get_data_directory() const -> std::string { [[nodiscard]] auto get_database_type() const -> database_type;
return data_directory_;
}
[[nodiscard]] auto get_enable_chunk_download_timeout() const -> bool { [[nodiscard]] auto get_data_directory() const -> std::string;
return enable_chunk_downloader_timeout_;
}
[[nodiscard]] auto get_enable_comm_duration_events() const -> bool { [[nodiscard]] auto get_download_timeout_secs() const -> std::uint8_t;
return enable_comm_duration_events_;
}
[[nodiscard]] auto get_enable_drive_events() const -> bool { [[nodiscard]] auto get_enable_download_timeout() const -> bool;
return enable_drive_events_;
}
[[nodiscard]] auto get_encrypt_config() const -> encrypt_config { [[nodiscard]] auto get_enable_drive_events() const -> bool;
return encrypt_config_;
} [[nodiscard]] auto get_encrypt_config() const -> encrypt_config;
#if defined(_WIN32) #if defined(_WIN32)
[[nodiscard]] auto get_enable_mount_manager() const -> bool { [[nodiscard]] auto get_enable_mount_manager() const -> bool;
return enable_mount_manager_; #endif // defined(_WIN32)
}
#endif
[[nodiscard]] auto get_enable_max_cache_size() const -> bool { [[nodiscard]] auto get_event_level() const -> event_level;
return enable_max_cache_size_;
}
[[nodiscard]] auto get_enable_remote_mount() const -> bool { [[nodiscard]] auto get_eviction_delay_mins() const -> std::uint32_t;
return enable_remote_mount_;
}
[[nodiscard]] auto get_event_level() const -> event_level { [[nodiscard]] auto get_eviction_uses_accessed_time() const -> bool;
return event_level_;
}
[[nodiscard]] auto get_eviction_delay_mins() const -> std::uint32_t { [[nodiscard]] auto get_high_frequency_interval_secs() const -> std::uint16_t;
return eviction_delay_mins_;
}
[[nodiscard]] auto get_eviction_uses_accessed_time() const -> bool { [[nodiscard]] auto get_host_config() const -> host_config;
return eviction_uses_accessed_time_;
}
[[nodiscard]] auto get_high_frequency_interval_secs() const -> std::uint8_t {
return std::max(static_cast<std::uint8_t>(1U), high_freq_interval_secs_);
}
[[nodiscard]] auto get_host_config() const -> host_config { return hc_; }
[[nodiscard]] auto get_is_remote_mount() const -> bool {
return is_remote_mount_;
}
[[nodiscard]] auto get_json() const -> json; [[nodiscard]] auto get_json() const -> json;
[[nodiscard]] auto get_log_directory() const -> std::string { [[nodiscard]] auto get_log_directory() const -> std::string;
return log_directory_;
}
[[nodiscard]] auto get_low_frequency_interval_secs() const -> std::uint32_t { [[nodiscard]] auto get_low_frequency_interval_secs() const -> std::uint16_t;
return std::max(1U, low_freq_interval_secs_);
}
[[nodiscard]] auto get_max_cache_size_bytes() const -> std::uint64_t; [[nodiscard]] auto get_max_cache_size_bytes() const -> std::uint64_t;
[[nodiscard]] auto get_max_upload_count() const -> std::uint8_t { [[nodiscard]] auto get_max_upload_count() const -> std::uint8_t;
return std::max(std::uint8_t(1U), max_upload_count_);
}
[[nodiscard]] auto get_online_check_retry_secs() const -> std::uint16_t { [[nodiscard]] auto get_med_frequency_interval_secs() const -> std::uint16_t;
return std::max(std::uint16_t(15U), online_check_retry_secs_);
}
[[nodiscard]] auto get_orphaned_file_retention_days() const -> std::uint16_t { [[nodiscard]] auto get_online_check_retry_secs() const -> std::uint16_t;
return std::min(static_cast<std::uint16_t>(31U),
std::max(static_cast<std::uint16_t>(1U),
orphaned_file_retention_days_));
}
[[nodiscard]] auto get_preferred_download_type() const -> download_type { [[nodiscard]] auto get_orphaned_file_retention_days() const -> std::uint16_t;
return download_type_from_string(preferred_download_type_,
download_type::fallback);
}
[[nodiscard]] auto get_provider_type() const -> provider_type { [[nodiscard]] auto get_preferred_download_type() const -> download_type;
return prov_;
}
[[nodiscard]] auto get_read_ahead_count() const -> std::uint8_t { [[nodiscard]] auto get_provider_type() const -> provider_type;
return std::max(static_cast<std::uint8_t>(1U), read_ahead_count_);
}
[[nodiscard]] auto get_remote_client_pool_size() const -> std::uint8_t { [[nodiscard]] auto get_remote_config() const -> remote::remote_config;
return std::max(static_cast<std::uint8_t>(5U), remote_client_pool_size_);
}
[[nodiscard]] auto get_remote_host_name_or_ip() const -> std::string { [[nodiscard]] auto get_remote_mount() const -> remote::remote_mount;
return remote_host_name_or_ip_;
}
[[nodiscard]] auto get_remote_max_connections() const -> std::uint8_t { [[nodiscard]] auto get_retry_read_count() const -> std::uint16_t;
return std::max(static_cast<std::uint8_t>(1U), remote_max_connections_);
}
[[nodiscard]] auto get_remote_port() const -> std::uint16_t { [[nodiscard]] auto get_ring_buffer_file_size() const -> std::uint16_t;
return remote_port_;
}
[[nodiscard]] auto get_remote_receive_timeout_secs() const -> std::uint16_t { [[nodiscard]] auto get_s3_config() const -> s3_config;
return remote_receive_timeout_secs_;
}
[[nodiscard]] auto get_remote_send_timeout_secs() const -> std::uint16_t { [[nodiscard]] auto get_sia_config() const -> sia_config;
return remote_send_timeout_secs_;
}
[[nodiscard]] auto get_remote_token() const -> std::string { [[nodiscard]] auto get_task_wait_ms() const -> std::uint16_t;
return remote_token_;
}
[[nodiscard]] auto get_retry_read_count() const -> std::uint16_t { [[nodiscard]] auto
return std::max(std::uint16_t(2), retry_read_count_); get_value_by_name(const std::string &name) const -> std::string;
}
[[nodiscard]] auto get_ring_buffer_file_size() const -> std::uint16_t { [[nodiscard]] auto get_version() const -> std::uint64_t;
return std::max(
static_cast<std::uint16_t>(64U),
std::min(static_cast<std::uint16_t>(1024U), ring_buffer_file_size_));
}
[[nodiscard]] auto get_s3_config() const -> s3_config { return s3_config_; }
[[nodiscard]] auto get_sia_config() const -> sia_config {
return sia_config_;
}
[[nodiscard]] auto get_value_by_name(const std::string &name) -> std::string;
[[nodiscard]] auto get_version() const -> std::uint64_t { return version_; }
void save(); void save();
void set_api_auth(const std::string &api_auth) { void set_api_auth(const std::string &value);
set_value(api_auth_, api_auth);
}
void set_api_port(std::uint16_t api_port) { set_value(api_port_, api_port); } void set_api_port(std::uint16_t value);
void set_api_user(const std::string &api_user) { void set_api_user(const std::string &value);
set_value(api_user_, api_user);
}
void set_chunk_downloader_timeout_secs( void set_download_timeout_secs(std::uint8_t value);
std::uint8_t chunk_downloader_timeout_secs) {
set_value(download_timeout_secs_, chunk_downloader_timeout_secs);
}
void void set_database_type(const database_type &value);
set_enable_chunk_downloader_timeout(bool enable_chunk_downloader_timeout) {
set_value(enable_chunk_downloader_timeout_,
enable_chunk_downloader_timeout);
}
void set_enable_comm_duration_events(bool enable_comm_duration_events) { void set_enable_download_timeout(bool value);
set_value(enable_comm_duration_events_, enable_comm_duration_events);
}
void set_enable_drive_events(bool enable_drive_events) { void set_enable_drive_events(bool value);
set_value(enable_drive_events_, enable_drive_events);
}
void set_enable_max_cache_size(bool enable_max_cache_size) {
set_value(enable_max_cache_size_, enable_max_cache_size);
}
#if defined(_WIN32) #if defined(_WIN32)
void set_enable_mount_manager(bool enable_mount_manager) { void set_enable_mount_manager(bool value);
set_value(enable_mount_manager_, enable_mount_manager); #endif // defined(_WIN32)
}
#endif
void set_enable_remote_mount(bool enable_remote_mount); void set_event_level(const event_level &value);
void set_event_level(const event_level &level) { void set_encrypt_config(encrypt_config value);
if (set_value(event_level_, level)) {
event_system::instance().raise<event_level_changed>(
event_level_to_string(level));
}
}
void set_eviction_delay_mins(std::uint32_t eviction_delay_mins) { void set_eviction_delay_mins(std::uint32_t value);
set_value(eviction_delay_mins_, eviction_delay_mins);
}
void set_eviction_uses_accessed_time(bool eviction_uses_accessed_time) { void set_eviction_uses_accessed_time(bool value);
set_value(eviction_uses_accessed_time_, eviction_uses_accessed_time);
}
void void set_high_frequency_interval_secs(std::uint16_t value);
set_high_frequency_interval_secs(std::uint8_t high_frequency_interval_secs) {
set_value(high_freq_interval_secs_, high_frequency_interval_secs);
}
#if defined(PROJECT_TESTING) void set_host_config(host_config value);
void set_host_config(host_config hc) {
config_changed_ = true;
hc_ = std::move(hc);
save();
}
void set_s3_config(s3_config s3) { void set_low_frequency_interval_secs(std::uint16_t value);
config_changed_ = true;
s3_config_ = std::move(s3);
save();
}
#endif
void set_is_remote_mount(bool is_remote_mount); void set_max_cache_size_bytes(std::uint64_t value);
void void set_max_upload_count(std::uint8_t value);
set_low_frequency_interval_secs(std::uint32_t low_frequency_interval_secs) {
set_value(low_freq_interval_secs_, low_frequency_interval_secs);
}
void set_max_cache_size_bytes(std::uint64_t max_cache_size_bytes) { void set_med_frequency_interval_secs(std::uint16_t value);
set_value(max_cache_size_bytes_, max_cache_size_bytes);
}
void set_max_upload_count(std::uint8_t max_upload_count) { void set_online_check_retry_secs(std::uint16_t value);
set_value(max_upload_count_, max_upload_count);
}
void set_online_check_retry_secs(std::uint16_t online_check_retry_secs) { void set_orphaned_file_retention_days(std::uint16_t value);
set_value(online_check_retry_secs_, online_check_retry_secs);
}
void void set_preferred_download_type(const download_type &value);
set_orphaned_file_retention_days(std::uint16_t orphaned_file_retention_days) {
set_value(orphaned_file_retention_days_, orphaned_file_retention_days);
}
void set_preferred_download_type(const download_type &dt) { void set_remote_config(remote::remote_config value);
set_value(preferred_download_type_, download_type_to_string(dt));
}
void set_read_ahead_count(std::uint8_t read_ahead_count) { void set_remote_mount(remote::remote_mount value);
set_value(read_ahead_count_, read_ahead_count);
}
void set_remote_client_pool_size(std::uint8_t remote_client_pool_size) { void set_retry_read_count(std::uint16_t value);
set_value(remote_client_pool_size_, remote_client_pool_size);
}
void set_ring_buffer_file_size(std::uint16_t ring_buffer_file_size) { void set_ring_buffer_file_size(std::uint16_t value);
set_value(ring_buffer_file_size_, ring_buffer_file_size);
}
void set_remote_host_name_or_ip(const std::string &remote_host_name_or_ip) { void set_s3_config(s3_config value);
set_value(remote_host_name_or_ip_, remote_host_name_or_ip);
}
void set_remote_max_connections(std::uint8_t remote_max_connections) { void set_sia_config(sia_config value);
set_value(remote_max_connections_, remote_max_connections);
}
void set_remote_port(std::uint16_t remote_port) { void set_task_wait_ms(std::uint16_t value);
set_value(remote_port_, remote_port);
}
void
set_remote_receive_timeout_secs(std::uint16_t remote_receive_timeout_secs) {
set_value(remote_receive_timeout_secs_, remote_receive_timeout_secs);
}
void set_remote_send_timeout_secs(std::uint16_t remote_send_timeout_secs) {
set_value(remote_send_timeout_secs_, remote_send_timeout_secs);
}
void set_remote_token(const std::string &remote_token) {
set_value(remote_token_, remote_token);
}
void set_retry_read_count(std::uint16_t retry_read_count) {
set_value(retry_read_count_, retry_read_count);
}
[[nodiscard]] auto set_value_by_name(const std::string &name, [[nodiscard]] auto set_value_by_name(const std::string &name,
const std::string &value) -> std::string; const std::string &value) -> std::string;

View File

@ -39,8 +39,8 @@ struct http_put_file final : http_request_base {
std::shared_ptr<utils::encryption::encrypting_reader> reader; std::shared_ptr<utils::encryption::encrypting_reader> reader;
std::string source_path; std::string source_path;
[[nodiscard]] auto [[nodiscard]] auto set_method(CURL *curl, stop_type &stop_requested) const
set_method(CURL *curl, stop_type &stop_requested) const -> bool override; -> bool override;
private: private:
mutable std::shared_ptr<read_file_info> read_info{}; mutable std::shared_ptr<read_file_info> read_info{};

View File

@ -26,9 +26,7 @@
#include "utils/file.hpp" #include "utils/file.hpp"
namespace repertory::curl::requests { namespace repertory::curl::requests {
using read_callback = size_t (*)(char *, size_t, size_t, void *); using curl_response_callback =
using response_callback =
std::function<void(const data_buffer &data, long response_code)>; std::function<void(const data_buffer &data, long response_code)>;
struct read_file_info final { struct read_file_info final {
@ -37,19 +35,8 @@ struct read_file_info final {
std::uint64_t offset{}; std::uint64_t offset{};
}; };
inline const auto read_file_data = static_cast<read_callback>( [[nodiscard]] auto curl_file_reader(char *buffer, size_t size, size_t nitems,
[](char *buffer, size_t size, size_t nitems, void *instream) -> size_t { void *instream) -> size_t;
auto *read_info = reinterpret_cast<read_file_info *>(instream);
std::size_t bytes_read{};
auto ret =
read_info->file->read(reinterpret_cast<unsigned char *>(buffer),
size * nitems, read_info->offset, &bytes_read);
if (ret) {
read_info->offset += bytes_read;
}
return ret && not read_info->stop_requested ? bytes_read
: CURL_READFUNC_ABORT;
});
struct http_request_base { struct http_request_base {
http_request_base() = default; http_request_base() = default;
@ -68,14 +55,15 @@ struct http_request_base {
std::string path{}; std::string path{};
http_query_parameters query{}; http_query_parameters query{};
std::optional<http_range> range{}; std::optional<http_range> range{};
std::optional<response_callback> response_handler; std::optional<curl_response_callback> response_handler;
std::optional<http_headers> response_headers; std::optional<http_headers> response_headers;
std::optional<std::uint64_t> total_size{}; std::optional<std::uint64_t> total_size{};
[[nodiscard]] virtual auto get_path() const -> std::string { return path; } [[nodiscard]] virtual auto get_path() const -> std::string { return path; }
[[nodiscard]] virtual auto [[nodiscard]] virtual auto set_method(CURL *curl,
set_method(CURL *curl, stop_type &stop_requested) const -> bool = 0; stop_type &stop_requested) const
-> bool = 0;
}; };
} // namespace repertory::curl::requests } // namespace repertory::curl::requests

View File

@ -52,23 +52,23 @@ public:
~packet() = default; ~packet() = default;
private: private:
data_buffer buffer_; data_buffer buffer_{};
std::size_t decode_offset_ = 0U; std::size_t decode_offset_{0U};
public: public:
[[nodiscard]] static auto decode_json(packet &response, [[nodiscard]] static auto decode_json(packet &response, json &json_data)
json &json_data) -> int; -> int;
public: public:
void clear(); void clear();
[[nodiscard]] auto current_pointer() -> unsigned char * { [[nodiscard]] auto current_pointer() -> unsigned char * {
return (decode_offset_ < buffer_.size()) ? &buffer_[decode_offset_] return (decode_offset_ < buffer_.size()) ? &buffer_.at(decode_offset_)
: nullptr; : nullptr;
} }
[[nodiscard]] auto current_pointer() const -> const unsigned char * { [[nodiscard]] auto current_pointer() const -> const unsigned char * {
return (decode_offset_ < buffer_.size()) ? &buffer_[decode_offset_] return (decode_offset_ < buffer_.size()) ? &buffer_.at(decode_offset_)
: nullptr; : nullptr;
} }
@ -206,7 +206,7 @@ public:
return static_cast<std::uint32_t>(buffer_.size()); return static_cast<std::uint32_t>(buffer_.size());
} }
void transfer_into(data_buffer &buffer); void to_buffer(data_buffer &buffer);
public: public:
auto operator=(const data_buffer &buffer) noexcept -> packet &; auto operator=(const data_buffer &buffer) noexcept -> packet &;
@ -226,8 +226,6 @@ public:
return buffer_.at(index); return buffer_.at(index);
} }
}; };
using packet = packet;
} // namespace repertory } // namespace repertory
#endif // REPERTORY_INCLUDE_COMM_PACKET_PACKET_HPP_ #endif // REPERTORY_INCLUDE_COMM_PACKET_PACKET_HPP_

View File

@ -23,6 +23,7 @@
#define REPERTORY_INCLUDE_COMM_PACKET_PACKET_CLIENT_HPP_ #define REPERTORY_INCLUDE_COMM_PACKET_PACKET_CLIENT_HPP_
#include "comm/packet/packet.hpp" #include "comm/packet/packet.hpp"
#include "types/remote.hpp"
using boost::asio::ip::tcp; using boost::asio::ip::tcp;
@ -36,9 +37,7 @@ private:
}; };
public: public:
packet_client(std::string host_name_or_ip, std::uint8_t max_connections, packet_client(remote::remote_config cfg);
std::uint16_t port, std::uint16_t receive_timeout,
std::uint16_t send_timeout, std::string encryption_token);
~packet_client(); ~packet_client();
@ -49,12 +48,7 @@ public:
private: private:
boost::asio::io_context io_context_; boost::asio::io_context io_context_;
std::string host_name_or_ip_; remote::remote_config cfg_;
std::uint8_t max_connections_;
std::uint16_t port_;
std::uint16_t receive_timeout_;
std::uint16_t send_timeout_;
std::string encryption_token_;
std::string unique_id_; std::string unique_id_;
private: private:
@ -75,21 +69,21 @@ private:
void put_client(std::shared_ptr<client> &cli); void put_client(std::shared_ptr<client> &cli);
[[nodiscard]] auto read_packet(client &cli, [[nodiscard]] auto read_packet(client &cli, packet &response)
packet &response) -> packet::error_type; -> packet::error_type;
void resolve(); void resolve();
public: public:
[[nodiscard]] auto send(std::string_view method, [[nodiscard]] auto send(std::string_view method, std::uint32_t &service_flags)
std::uint32_t &service_flags) -> packet::error_type; -> packet::error_type;
[[nodiscard]] auto send(std::string_view method, packet &request, [[nodiscard]] auto send(std::string_view method, packet &request,
std::uint32_t &service_flags) -> packet::error_type; std::uint32_t &service_flags) -> packet::error_type;
[[nodiscard]] auto send(std::string_view method, packet &request, [[nodiscard]] auto send(std::string_view method, packet &request,
packet &response, packet &response, std::uint32_t &service_flags)
std::uint32_t &service_flags) -> packet::error_type; -> packet::error_type;
}; };
} // namespace repertory } // namespace repertory

View File

@ -52,8 +52,8 @@ public:
private: private:
struct connection { struct connection {
connection(boost::asio::io_service &io_service, tcp::acceptor &acceptor_) connection(io_context &ctx, tcp::acceptor &acceptor_)
: socket(io_service), acceptor(acceptor_) {} : socket(ctx), acceptor(acceptor_) {}
tcp::socket socket; tcp::socket socket;
tcp::acceptor &acceptor; tcp::acceptor &acceptor;
@ -68,7 +68,7 @@ private:
std::string encryption_token_; std::string encryption_token_;
closed_callback closed_; closed_callback closed_;
message_handler_callback message_handler_; message_handler_callback message_handler_;
boost::asio::io_context io_context_; io_context io_context_;
std::unique_ptr<std::thread> server_thread_; std::unique_ptr<std::thread> server_thread_;
std::vector<std::thread> service_threads_; std::vector<std::thread> service_threads_;
std::recursive_mutex connection_mutex_; std::recursive_mutex connection_mutex_;

View File

@ -221,44 +221,25 @@ using WCHAR = wchar_t;
#define MAX_PATH 260 #define MAX_PATH 260
#define STATUS_SUCCESS \ #define STATUS_SUCCESS std::uint32_t{0U}
std::uint32_t { 0U } #define STATUS_ACCESS_DENIED std::uint32_t{0xC0000022L}
#define STATUS_ACCESS_DENIED \ #define STATUS_DEVICE_BUSY std::uint32_t{0x80000011L}
std::uint32_t { 0xC0000022L } #define STATUS_DEVICE_INSUFFICIENT_RESOURCES std::uint32_t{0xC0000468L}
#define STATUS_DEVICE_BUSY \ #define STATUS_DIRECTORY_NOT_EMPTY std::uint32_t{0xC0000101L}
std::uint32_t { 0x80000011L } #define STATUS_FILE_IS_A_DIRECTORY std::uint32_t{0xC00000BAL}
#define STATUS_DEVICE_INSUFFICIENT_RESOURCES \ #define STATUS_FILE_TOO_LARGE std::uint32_t{0xC0000904L}
std::uint32_t { 0xC0000468L } #define STATUS_INSUFFICIENT_RESOURCES std::uint32_t{0xC000009AL}
#define STATUS_DIRECTORY_NOT_EMPTY \ #define STATUS_INTERNAL_ERROR std::uint32_t{0xC00000E5L}
std::uint32_t { 0xC0000101L } #define STATUS_INVALID_ADDRESS std::uint32_t{0xC0000141L}
#define STATUS_FILE_IS_A_DIRECTORY \ #define STATUS_INVALID_HANDLE std::uint32_t{0xC0000006L}
std::uint32_t { 0xC00000BAL } #define STATUS_INVALID_IMAGE_FORMAT std::uint32_t{0xC000007BL}
#define STATUS_FILE_TOO_LARGE \ #define STATUS_INVALID_PARAMETER std::uint32_t{0xC000000DL}
std::uint32_t { 0xC0000904L } #define STATUS_NO_MEMORY std::uint32_t{0xC0000017L}
#define STATUS_INSUFFICIENT_RESOURCES \ #define STATUS_NOT_IMPLEMENTED std::uint32_t{0xC0000002L}
std::uint32_t { 0xC000009AL } #define STATUS_OBJECT_NAME_EXISTS std::uint32_t{0x40000000L}
#define STATUS_INTERNAL_ERROR \ #define STATUS_OBJECT_NAME_NOT_FOUND std::uint32_t{0xC0000034L}
std::uint32_t { 0xC00000E5L } #define STATUS_OBJECT_PATH_INVALID std::uint32_t{0xC0000039L}
#define STATUS_INVALID_ADDRESS \ #define STATUS_UNEXPECTED_IO_ERROR std::uint32_t{0xC00000E9L}
std::uint32_t { 0xC0000141L }
#define STATUS_INVALID_HANDLE \
std::uint32_t { 0xC0000006L }
#define STATUS_INVALID_IMAGE_FORMAT \
std::uint32_t { 0xC000007BL }
#define STATUS_INVALID_PARAMETER \
std::uint32_t { 0xC000000DL }
#define STATUS_NO_MEMORY \
std::uint32_t { 0xC0000017L }
#define STATUS_NOT_IMPLEMENTED \
std::uint32_t { 0xC0000002L }
#define STATUS_OBJECT_NAME_EXISTS \
std::uint32_t { 0x40000000L }
#define STATUS_OBJECT_NAME_NOT_FOUND \
std::uint32_t { 0xC0000034L }
#define STATUS_OBJECT_PATH_INVALID \
std::uint32_t { 0xC0000039L }
#define STATUS_UNEXPECTED_IO_ERROR \
std::uint32_t { 0xC00000E9L }
#define CONVERT_STATUS_NOT_IMPLEMENTED(e) \ #define CONVERT_STATUS_NOT_IMPLEMENTED(e) \
((std::uint32_t(e) == STATUS_NOT_IMPLEMENTED) ? -ENOTSUP : e) ((std::uint32_t(e) == STATUS_NOT_IMPLEMENTED) ? -ENOTSUP : e)
@ -296,8 +277,8 @@ using namespace Fsp;
#define INTERFACE_SETUP(name) \ #define INTERFACE_SETUP(name) \
public: \ public: \
name(const name &) noexcept = delete; \ name(const name &) noexcept = delete; \
name &operator=(const name &) noexcept = delete; \ auto operator=(const name &) noexcept -> name & = delete; \
name &operator=(name &&) noexcept = delete; \ auto operator=(name &&) noexcept -> name & = delete; \
\ \
protected: \ protected: \
name() = default; \ name() = default; \

View File

@ -0,0 +1,34 @@
/*
Copyright <2018-2024> <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 REPERTORY_INCLUDE_DB_FILE_DB_HPP_
#define REPERTORY_INCLUDE_DB_FILE_DB_HPP_
#include "db/i_file_db.hpp"
namespace repertory {
class app_config;
[[nodiscard]] auto create_file_db(const app_config &cfg)
-> std::unique_ptr<i_file_db>;
} // namespace repertory
#endif // REPERTORY_INCLUDE_DB_FILE_DB_HPP_

View File

@ -0,0 +1,34 @@
/*
Copyright <2018-2024> <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 REPERTORY_INCLUDE_DB_FILE_MGR_DB_HPP_
#define REPERTORY_INCLUDE_DB_FILE_MGR_DB_HPP_
#include "db/i_file_mgr_db.hpp"
namespace repertory {
class app_config;
[[nodiscard]] auto
create_file_mgr_db(const app_config &cfg) -> std::unique_ptr<i_file_mgr_db>;
} // namespace repertory
#endif // REPERTORY_INCLUDE_DB_FILE_MGR_DB_HPP_

View File

@ -0,0 +1,95 @@
/*
Copyright <2018-2024> <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 REPERTORY_INCLUDE_DB_I_FILE_DB_HPP_
#define REPERTORY_INCLUDE_DB_I_FILE_DB_HPP_
#include "types/repertory.hpp"
namespace repertory {
class i_file_db {
INTERFACE_SETUP(i_file_db);
public:
struct file_info final {
std::string api_path;
bool directory;
std::string source_path;
};
struct file_data final {
std::string api_path;
std::uint64_t file_size{};
std::vector<
std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>
iv_list{};
std::string source_path;
};
public:
[[nodiscard]] virtual auto add_directory(const std::string &api_path,
const std::string &source_path)
-> api_error = 0;
[[nodiscard]] virtual auto add_or_update_file(const file_data &data)
-> api_error = 0;
virtual void clear() = 0;
[[nodiscard]] virtual auto count() const -> std::uint64_t = 0;
[[nodiscard]] virtual auto get_api_path(const std::string &source_path,
std::string &api_path) const
-> api_error = 0;
[[nodiscard]] virtual auto
get_directory_api_path(const std::string &source_path,
std::string &api_path) const -> api_error = 0;
[[nodiscard]] virtual auto
get_directory_source_path(const std::string &api_path,
std::string &source_path) const -> api_error = 0;
[[nodiscard]] virtual auto get_file_api_path(const std::string &source_path,
std::string &api_path) const
-> api_error = 0;
[[nodiscard]] virtual auto get_file_data(const std::string &api_path,
file_data &data) const
-> api_error = 0;
[[nodiscard]] virtual auto
get_file_source_path(const std::string &api_path,
std::string &source_path) const -> api_error = 0;
[[nodiscard]] virtual auto get_item_list() const
-> std::vector<file_info> = 0;
[[nodiscard]] virtual auto get_source_path(const std::string &api_path,
std::string &source_path) const
-> api_error = 0;
[[nodiscard]] virtual auto remove_item(const std::string &api_path)
-> api_error = 0;
};
} // namespace repertory
#endif // REPERTORY_INCLUDE_DB_I_FILE_DB_HPP_

View File

@ -0,0 +1,86 @@
/*
Copyright <2018-2024> <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 REPERTORY_INCLUDE_DB_I_FILE_MGR_DB_HPP_
#define REPERTORY_INCLUDE_DB_I_FILE_MGR_DB_HPP_
#include "types/repertory.hpp"
namespace repertory {
class i_file_mgr_db {
INTERFACE_SETUP(i_file_mgr_db);
public:
struct resume_entry final {
std::string api_path;
std::uint64_t chunk_size{};
boost::dynamic_bitset<> read_state;
std::string source_path;
};
struct upload_active_entry final {
std::string api_path;
std::string source_path;
};
struct upload_entry final {
std::string api_path;
std::string source_path;
};
public:
[[nodiscard]] virtual auto add_resume(const resume_entry &entry) -> bool = 0;
[[nodiscard]] virtual auto add_upload(const upload_entry &entry) -> bool = 0;
[[nodiscard]] virtual auto add_upload_active(const upload_active_entry &entry)
-> bool = 0;
virtual void clear() = 0;
[[nodiscard]] virtual auto get_next_upload() const
-> std::optional<upload_entry> = 0;
[[nodiscard]] virtual auto get_resume_list() const
-> std::vector<resume_entry> = 0;
[[nodiscard]] virtual auto get_upload(const std::string &api_path) const
-> std::optional<upload_entry> = 0;
[[nodiscard]] virtual auto get_upload_active_list() const
-> std::vector<upload_active_entry> = 0;
[[nodiscard]] virtual auto remove_resume(const std::string &api_path)
-> bool = 0;
[[nodiscard]] virtual auto remove_upload(const std::string &api_path)
-> bool = 0;
[[nodiscard]] virtual auto remove_upload_active(const std::string &api_path)
-> bool = 0;
[[nodiscard]] virtual auto rename_resume(const std::string &from_api_path,
const std::string &to_api_path)
-> bool = 0;
};
} // namespace repertory
#endif // REPERTORY_INCLUDE_DB_I_FILE_MGR_DB_HPP_

View File

@ -0,0 +1,78 @@
/*
Copyright <2018-2024> <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 REPERTORY_INCLUDE_DB_I_META_DB_HPP_
#define REPERTORY_INCLUDE_DB_I_META_DB_HPP_
#include "types/repertory.hpp"
namespace repertory {
class i_meta_db {
INTERFACE_SETUP(i_meta_db);
public:
virtual void clear() = 0;
[[nodiscard]] virtual auto get_api_path(const std::string &source_path,
std::string &api_path) const
-> api_error = 0;
[[nodiscard]] virtual auto get_api_path_list() const
-> std::vector<std::string> = 0;
[[nodiscard]] virtual auto get_item_meta(const std::string &api_path,
api_meta_map &meta) const
-> api_error = 0;
[[nodiscard]] virtual auto get_item_meta(const std::string &api_path,
const std::string &key,
std::string &value) const
-> api_error = 0;
[[nodiscard]] virtual auto get_pinned_files() const
-> std::vector<std::string> = 0;
[[nodiscard]] virtual auto get_total_item_count() const -> std::uint64_t = 0;
[[nodiscard]] virtual auto get_total_size() const -> std::uint64_t = 0;
virtual void remove_api_path(const std::string &api_path) = 0;
[[nodiscard]] virtual auto remove_item_meta(const std::string &api_path,
const std::string &key)
-> api_error = 0;
[[nodiscard]] virtual auto rename_item_meta(const std::string &from_api_path,
const std::string &to_api_path)
-> api_error = 0;
[[nodiscard]] virtual auto set_item_meta(const std::string &api_path,
const std::string &key,
const std::string &value)
-> api_error = 0;
[[nodiscard]] virtual auto set_item_meta(const std::string &api_path,
const api_meta_map &meta)
-> api_error = 0;
};
} // namespace repertory
#endif // REPERTORY_INCLUDE_DB_I_META_DB_HPP_

View File

@ -0,0 +1,117 @@
/*
Copyright <2018-2024> <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 REPERTORY_INCLUDE_DB_IMPL_RDB_FILE_DB_HPP_
#define REPERTORY_INCLUDE_DB_IMPL_RDB_FILE_DB_HPP_
#include "db/i_file_db.hpp"
namespace repertory {
class app_config;
class rdb_file_db final : public i_file_db {
public:
rdb_file_db(const app_config &cfg);
~rdb_file_db() override;
rdb_file_db(const rdb_file_db &) = delete;
rdb_file_db(rdb_file_db &&) = delete;
auto operator=(const rdb_file_db &) -> rdb_file_db & = delete;
auto operator=(rdb_file_db &&) -> rdb_file_db & = delete;
private:
const app_config &cfg_;
private:
std::unique_ptr<rocksdb::TransactionDB> db_{nullptr};
rocksdb::ColumnFamilyHandle *directory_family_{};
rocksdb::ColumnFamilyHandle *file_family_{};
rocksdb::ColumnFamilyHandle *path_family_{};
rocksdb::ColumnFamilyHandle *source_family_{};
private:
void create_or_open(bool clear);
[[nodiscard]] auto create_iterator(rocksdb::ColumnFamilyHandle *family) const
-> std::shared_ptr<rocksdb::Iterator>;
[[nodiscard]] static auto
perform_action(std::string_view function_name,
std::function<rocksdb::Status()> action) -> api_error;
[[nodiscard]] auto perform_action(
std::string_view function_name,
std::function<rocksdb::Status(rocksdb::Transaction *txn)> action)
-> api_error;
[[nodiscard]] auto remove_item(const std::string &api_path,
const std::string &source_path,
rocksdb::Transaction *txn) -> rocksdb::Status;
public:
[[nodiscard]] auto
add_directory(const std::string &api_path,
const std::string &source_path) -> api_error override;
[[nodiscard]] auto
add_or_update_file(const i_file_db::file_data &data) -> api_error override;
void clear() override;
[[nodiscard]] auto count() const -> std::uint64_t override;
[[nodiscard]] auto
get_api_path(const std::string &source_path,
std::string &api_path) const -> api_error override;
[[nodiscard]] auto
get_directory_api_path(const std::string &source_path,
std::string &api_path) const -> api_error override;
[[nodiscard]] auto get_directory_source_path(const std::string &api_path,
std::string &source_path) const
-> api_error override;
[[nodiscard]] auto
get_file_api_path(const std::string &source_path,
std::string &api_path) const -> api_error override;
[[nodiscard]] auto
get_file_data(const std::string &api_path,
i_file_db::file_data &data) const -> api_error override;
[[nodiscard]] auto
get_file_source_path(const std::string &api_path,
std::string &source_path) const -> api_error override;
[[nodiscard]] auto
get_item_list() const -> std::vector<i_file_db::file_info> override;
[[nodiscard]] auto
get_source_path(const std::string &api_path,
std::string &source_path) const -> api_error override;
[[nodiscard]] auto
remove_item(const std::string &api_path) -> api_error override;
};
} // namespace repertory
#endif // REPERTORY_INCLUDE_DB_IMPL_RDB_FILE_DB_HPP_

View File

@ -0,0 +1,109 @@
/*
Copyright <2018-2024> <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 REPERTORY_INCLUDE_DB_IMPL_RDB_FILE_MGR_DB_HPP_
#define REPERTORY_INCLUDE_DB_IMPL_RDB_FILE_MGR_DB_HPP_
#include "db/i_file_mgr_db.hpp"
namespace repertory {
class app_config;
class rdb_file_mgr_db final : public i_file_mgr_db {
public:
rdb_file_mgr_db(const app_config &cfg);
~rdb_file_mgr_db() override;
rdb_file_mgr_db(const rdb_file_mgr_db &) = delete;
rdb_file_mgr_db(rdb_file_mgr_db &&) = delete;
auto operator=(const rdb_file_mgr_db &) -> rdb_file_mgr_db & = delete;
auto operator=(rdb_file_mgr_db &&) -> rdb_file_mgr_db & = delete;
private:
const app_config &cfg_;
private:
std::unique_ptr<rocksdb::TransactionDB> db_{nullptr};
std::atomic<std::uint64_t> id_{0U};
rocksdb::ColumnFamilyHandle *resume_family_{};
rocksdb::ColumnFamilyHandle *upload_active_family_{};
rocksdb::ColumnFamilyHandle *upload_family_{};
private:
void create_or_open(bool clear);
[[nodiscard]] auto create_iterator(rocksdb::ColumnFamilyHandle *family) const
-> std::shared_ptr<rocksdb::Iterator>;
[[nodiscard]] static auto
perform_action(std::string_view function_name,
std::function<rocksdb::Status()> action) -> bool;
[[nodiscard]] auto perform_action(
std::string_view function_name,
std::function<rocksdb::Status(rocksdb::Transaction *txn)> action) -> bool;
[[nodiscard]] auto remove_resume(const std::string &api_path,
rocksdb::Transaction *txn)
-> rocksdb::Status;
[[nodiscard]] auto add_resume(const resume_entry &entry,
rocksdb::Transaction *txn) -> rocksdb::Status;
public:
[[nodiscard]] auto add_resume(const resume_entry &entry) -> bool override;
[[nodiscard]] auto add_upload(const upload_entry &entry) -> bool override;
[[nodiscard]] auto add_upload_active(const upload_active_entry &entry)
-> bool override;
void clear() override;
[[nodiscard]] auto get_next_upload() const
-> std::optional<upload_entry> override;
[[nodiscard]] auto get_resume_list() const
-> std::vector<resume_entry> override;
[[nodiscard]] auto get_upload(const std::string &api_path) const
-> std::optional<upload_entry> override;
[[nodiscard]] auto get_upload_active_list() const
-> std::vector<upload_active_entry> override;
[[nodiscard]] auto remove_resume(const std::string &api_path)
-> bool override;
[[nodiscard]] auto remove_upload(const std::string &api_path)
-> bool override;
[[nodiscard]] auto remove_upload_active(const std::string &api_path)
-> bool override;
[[nodiscard]] auto rename_resume(const std::string &from_api_path,
const std::string &to_api_path)
-> bool override;
};
} // namespace repertory
#endif // REPERTORY_INCLUDE_DB_IMPL_RDB_FILE_MGR_DB_HPP_

View File

@ -0,0 +1,127 @@
/*
Copyright <2018-2024> <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 REPERTORY_INCLUDE_DB_IMPL_RDB_META_DB_HPP_
#define REPERTORY_INCLUDE_DB_IMPL_RDB_META_DB_HPP_
#include "db/i_meta_db.hpp"
#include "types/repertory.hpp"
namespace repertory {
class app_config;
class rdb_meta_db final : public i_meta_db {
public:
rdb_meta_db(const app_config &cfg);
~rdb_meta_db() override;
rdb_meta_db(const rdb_meta_db &) = delete;
rdb_meta_db(rdb_meta_db &&) = delete;
auto operator=(const rdb_meta_db &) -> rdb_meta_db & = delete;
auto operator=(rdb_meta_db &&) -> rdb_meta_db & = delete;
private:
const app_config &cfg_;
private:
std::unique_ptr<rocksdb::TransactionDB> db_{nullptr};
rocksdb::ColumnFamilyHandle *meta_family_{};
rocksdb::ColumnFamilyHandle *pinned_family_{};
rocksdb::ColumnFamilyHandle *size_family_{};
rocksdb::ColumnFamilyHandle *source_family_{};
private:
[[nodiscard]] auto create_iterator(rocksdb::ColumnFamilyHandle *family) const
-> std::shared_ptr<rocksdb::Iterator>;
void create_or_open(bool clear);
[[nodiscard]] auto get_item_meta_json(const std::string &api_path,
json &json_data) const -> api_error;
[[nodiscard]] static auto
perform_action(std::string_view function_name,
std::function<rocksdb::Status()> action) -> api_error;
[[nodiscard]] auto perform_action(
std::string_view function_name,
std::function<rocksdb::Status(rocksdb::Transaction *txn)> action)
-> api_error;
[[nodiscard]] auto remove_api_path(const std::string &api_path,
const std::string &source_path,
rocksdb::Transaction *txn)
-> rocksdb::Status;
[[nodiscard]] auto update_item_meta(const std::string &api_path,
json json_data,
rocksdb::Transaction *base_txn = nullptr,
rocksdb::Status *status = nullptr)
-> api_error;
public:
void clear() override;
[[nodiscard]] auto get_api_path(const std::string &source_path,
std::string &api_path) const
-> api_error override;
[[nodiscard]] auto get_api_path_list() const
-> std::vector<std::string> override;
[[nodiscard]] auto get_item_meta(const std::string &api_path,
api_meta_map &meta) const
-> api_error override;
[[nodiscard]] auto get_item_meta(const std::string &api_path,
const std::string &key,
std::string &value) const
-> api_error override;
[[nodiscard]] auto get_pinned_files() const
-> std::vector<std::string> override;
[[nodiscard]] auto get_total_item_count() const -> std::uint64_t override;
[[nodiscard]] auto get_total_size() const -> std::uint64_t override;
void remove_api_path(const std::string &api_path) override;
[[nodiscard]] auto remove_item_meta(const std::string &api_path,
const std::string &key)
-> api_error override;
[[nodiscard]] auto rename_item_meta(const std::string &from_api_path,
const std::string &to_api_path)
-> api_error override;
[[nodiscard]] auto set_item_meta(const std::string &api_path,
const std::string &key,
const std::string &value)
-> api_error override;
[[nodiscard]] auto set_item_meta(const std::string &api_path,
const api_meta_map &meta)
-> api_error override;
};
} // namespace repertory
#endif // REPERTORY_INCLUDE_DB_IMPL_RDB_META_DB_HPP_

View File

@ -0,0 +1,92 @@
/*
Copyright <2018-2024> <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 REPERTORY_INCLUDE_DB_IMPL_SQLITE_FILE_DB_HPP_
#define REPERTORY_INCLUDE_DB_IMPL_SQLITE_FILE_DB_HPP_
#include "db/i_file_db.hpp"
#include "utils/db/sqlite/db_common.hpp"
namespace repertory {
class app_config;
class sqlite_file_db final : public i_file_db {
public:
sqlite_file_db(const app_config &cfg);
~sqlite_file_db() override;
sqlite_file_db(const sqlite_file_db &) = delete;
sqlite_file_db(sqlite_file_db &&) = delete;
auto operator=(const sqlite_file_db &) -> sqlite_file_db & = delete;
auto operator=(sqlite_file_db &&) -> sqlite_file_db & = delete;
private:
utils::db::sqlite::db3_t db_;
public:
[[nodiscard]] auto add_directory(const std::string &api_path,
const std::string &source_path)
-> api_error override;
[[nodiscard]] auto add_or_update_file(const i_file_db::file_data &data)
-> api_error override;
void clear() override;
[[nodiscard]] auto count() const -> std::uint64_t override;
[[nodiscard]] auto get_api_path(const std::string &source_path,
std::string &api_path) const
-> api_error override;
[[nodiscard]] auto get_directory_api_path(const std::string &source_path,
std::string &api_path) const
-> api_error override;
[[nodiscard]] auto get_directory_source_path(const std::string &api_path,
std::string &source_path) const
-> api_error override;
[[nodiscard]] auto get_file_api_path(const std::string &source_path,
std::string &api_path) const
-> api_error override;
[[nodiscard]] auto get_file_data(const std::string &api_path,
i_file_db::file_data &data) const
-> api_error override;
[[nodiscard]] auto get_file_source_path(const std::string &api_path,
std::string &source_path) const
-> api_error override;
[[nodiscard]] auto get_item_list() const
-> std::vector<i_file_db::file_info> override;
[[nodiscard]] auto get_source_path(const std::string &api_path,
std::string &source_path) const
-> api_error override;
[[nodiscard]] auto remove_item(const std::string &api_path)
-> api_error override;
};
} // namespace repertory
#endif // REPERTORY_INCLUDE_DB_IMPL_SQLITE_FILE_DB_HPP_

View File

@ -0,0 +1,82 @@
/*
Copyright <2018-2024> <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 REPERTORY_INCLUDE_DB_IMPL_SQLITE_FILE_MGR_DB_HPP_
#define REPERTORY_INCLUDE_DB_IMPL_SQLITE_FILE_MGR_DB_HPP_
#include "db/i_file_mgr_db.hpp"
#include "utils/db/sqlite/db_common.hpp"
namespace repertory {
class app_config;
class sqlite_file_mgr_db final : public i_file_mgr_db {
public:
sqlite_file_mgr_db(const app_config &cfg);
~sqlite_file_mgr_db() override;
sqlite_file_mgr_db(const sqlite_file_mgr_db &) = delete;
sqlite_file_mgr_db(sqlite_file_mgr_db &&) = delete;
auto operator=(const sqlite_file_mgr_db &) -> sqlite_file_mgr_db & = delete;
auto operator=(sqlite_file_mgr_db &&) -> sqlite_file_mgr_db & = delete;
private:
utils::db::sqlite::db3_t db_;
public:
[[nodiscard]] auto add_resume(const resume_entry &entry) -> bool override;
[[nodiscard]] auto add_upload(const upload_entry &entry) -> bool override;
[[nodiscard]] auto add_upload_active(const upload_active_entry &entry)
-> bool override;
void clear() override;
[[nodiscard]] auto get_next_upload() const
-> std::optional<upload_entry> override;
[[nodiscard]] auto get_resume_list() const
-> std::vector<resume_entry> override;
[[nodiscard]] auto get_upload(const std::string &api_path) const
-> std::optional<upload_entry> override;
[[nodiscard]] auto get_upload_active_list() const
-> std::vector<upload_active_entry> override;
[[nodiscard]] auto remove_resume(const std::string &api_path)
-> bool override;
[[nodiscard]] auto remove_upload(const std::string &api_path)
-> bool override;
[[nodiscard]] auto remove_upload_active(const std::string &api_path)
-> bool override;
[[nodiscard]] auto rename_resume(const std::string &from_api_path,
const std::string &to_api_path)
-> bool override;
};
} // namespace repertory
#endif // REPERTORY_INCLUDE_DB_IMPL_SQLITE_FILE_MGR_DB_HPP_

View File

@ -19,24 +19,25 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#ifndef REPERTORY_INCLUDE_PROVIDERS_META_DB_HPP_ #ifndef REPERTORY_INCLUDE_DB_IMPL_SQLITE_META_DB_HPP_
#define REPERTORY_INCLUDE_PROVIDERS_META_DB_HPP_ #define REPERTORY_INCLUDE_DB_IMPL_SQLITE_META_DB_HPP_
#include "db/i_meta_db.hpp"
#include "types/repertory.hpp" #include "types/repertory.hpp"
#include "utils/db/sqlite/db_common.hpp" #include "utils/db/sqlite/db_common.hpp"
namespace repertory { namespace repertory {
class app_config; class app_config;
class meta_db final { class sqlite_meta_db final : public i_meta_db {
public: public:
meta_db(const app_config &cfg); sqlite_meta_db(const app_config &cfg);
~meta_db(); ~sqlite_meta_db() override;
meta_db(const meta_db &) = delete; sqlite_meta_db(const sqlite_meta_db &) = delete;
meta_db(meta_db &&) = delete; sqlite_meta_db(sqlite_meta_db &&) = delete;
auto operator=(const meta_db &) -> meta_db & = delete; auto operator=(const sqlite_meta_db &) -> sqlite_meta_db & = delete;
auto operator=(meta_db &&) -> meta_db & = delete; auto operator=(sqlite_meta_db &&) -> sqlite_meta_db & = delete;
private: private:
utils::db::sqlite::db3_t db_; utils::db::sqlite::db3_t db_;
@ -47,38 +48,50 @@ private:
api_meta_map meta) -> api_error; api_meta_map meta) -> api_error;
public: public:
[[nodiscard]] auto get_api_path(const std::string &source_path, void clear() override;
std::string &api_path) -> api_error;
[[nodiscard]] auto get_api_path_list() -> std::vector<std::string>; [[nodiscard]] auto get_api_path(const std::string &source_path,
std::string &api_path) const
-> api_error override;
[[nodiscard]] auto get_api_path_list() const
-> std::vector<std::string> override;
[[nodiscard]] auto get_item_meta(const std::string &api_path, [[nodiscard]] auto get_item_meta(const std::string &api_path,
api_meta_map &meta) -> api_error; api_meta_map &meta) const
-> api_error override;
[[nodiscard]] auto get_item_meta(const std::string &api_path, [[nodiscard]] auto get_item_meta(const std::string &api_path,
const std::string &key, const std::string &key,
std::string &value) const -> api_error; std::string &value) const
-> api_error override;
[[nodiscard]] auto get_pinned_files() const -> std::vector<std::string>; [[nodiscard]] auto get_pinned_files() const
-> std::vector<std::string> override;
[[nodiscard]] auto get_total_item_count() const -> std::uint64_t; [[nodiscard]] auto get_total_item_count() const -> std::uint64_t override;
void remove_api_path(const std::string &api_path); [[nodiscard]] auto get_total_size() const -> std::uint64_t override;
void remove_api_path(const std::string &api_path) override;
[[nodiscard]] auto remove_item_meta(const std::string &api_path, [[nodiscard]] auto remove_item_meta(const std::string &api_path,
const std::string &key) -> api_error; const std::string &key)
-> api_error override;
[[nodiscard]] auto [[nodiscard]] auto rename_item_meta(const std::string &from_api_path,
rename_item_meta(const std::string &from_api_path, const std::string &to_api_path)
const std::string &to_api_path) -> api_error; -> api_error override;
[[nodiscard]] auto set_item_meta(const std::string &api_path, [[nodiscard]] auto set_item_meta(const std::string &api_path,
const std::string &key, const std::string &key,
const std::string &value) -> api_error; const std::string &value)
-> api_error override;
[[nodiscard]] auto set_item_meta(const std::string &api_path, [[nodiscard]] auto set_item_meta(const std::string &api_path,
const api_meta_map &meta) -> api_error; const api_meta_map &meta)
-> api_error override;
}; };
} // namespace repertory } // namespace repertory
#endif // REPERTORY_INCLUDE_PROVIDERS_META_DB_HPP_ #endif // REPERTORY_INCLUDE_DB_IMPL_SQLITE_META_DB_HPP_

View File

@ -0,0 +1,34 @@
/*
Copyright <2018-2024> <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 REPERTORY_INCLUDE_DB_META_DB_HPP_
#define REPERTORY_INCLUDE_DB_META_DB_HPP_
#include "db/i_meta_db.hpp"
namespace repertory {
class app_config;
[[nodiscard]] auto create_meta_db(const app_config &cfg)
-> std::unique_ptr<i_meta_db>;
} // namespace repertory
#endif // REPERTORY_INCLUDE_DB_META_DB_HPP_

View File

@ -34,7 +34,7 @@ public:
private: private:
struct open_directory final { struct open_directory final {
std::shared_ptr<directory_iterator> iterator; std::shared_ptr<directory_iterator> iterator;
std::vector<std::uint64_t> handles{}; std::vector<std::uint64_t> handles;
std::chrono::system_clock::time_point last_update{ std::chrono::system_clock::time_point last_update{
std::chrono::system_clock::now()}; std::chrono::system_clock::now()};
}; };
@ -60,8 +60,8 @@ public:
void execute_action(const std::string &api_path, void execute_action(const std::string &api_path,
const execute_callback &execute); const execute_callback &execute);
[[nodiscard]] auto [[nodiscard]] auto get_directory(std::uint64_t handle)
get_directory(std::uint64_t handle) -> std::shared_ptr<directory_iterator>; -> std::shared_ptr<directory_iterator>;
[[nodiscard]] auto remove_directory(const std::string &api_path) [[nodiscard]] auto remove_directory(const std::string &api_path)
-> std::shared_ptr<directory_iterator>; -> std::shared_ptr<directory_iterator>;

View File

@ -31,22 +31,23 @@ class i_provider;
class eviction final : public single_thread_service_base { class eviction final : public single_thread_service_base {
public: public:
eviction(i_provider &provider, const app_config &config, i_file_manager &fm) eviction(i_provider &provider, const app_config &config,
i_file_manager &file_mgr)
: single_thread_service_base("eviction"), : single_thread_service_base("eviction"),
provider_(provider),
config_(config), config_(config),
fm_(fm) {} file_mgr_(file_mgr),
provider_(provider) {}
~eviction() override = default; ~eviction() override = default;
private: private:
i_provider &provider_;
const app_config &config_; const app_config &config_;
i_file_manager &fm_; i_file_manager &file_mgr_;
i_provider &provider_;
private: private:
[[nodiscard]] auto [[nodiscard]] auto check_minimum_requirements(const std::string &file_path)
check_minimum_requirements(const std::string &file_path) -> bool; -> bool;
[[nodiscard]] auto get_filtered_cached_files() -> std::deque<std::string>; [[nodiscard]] auto get_filtered_cached_files() -> std::deque<std::string>;

View File

@ -103,7 +103,7 @@ protected:
struct fuse_file_info *file_info) -> api_error override; struct fuse_file_info *file_info) -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto
fgetattr_impl(std::string api_path, struct stat *st, fgetattr_impl(std::string api_path, struct stat *unix_st,
struct fuse_file_info *file_info) -> api_error override; struct fuse_file_info *file_info) -> api_error override;
#if defined(__APPLE__) #if defined(__APPLE__)
@ -124,11 +124,11 @@ protected:
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
[[nodiscard]] auto [[nodiscard]] auto
getattr_impl(std::string api_path, struct stat *st, getattr_impl(std::string api_path, struct stat *unix_st,
struct fuse_file_info *file_info) -> api_error override; struct fuse_file_info *file_info) -> api_error override;
#else #else
[[nodiscard]] auto getattr_impl(std::string api_path, [[nodiscard]] auto getattr_impl(std::string api_path,
struct stat *st) -> api_error override; struct stat *unix_st) -> api_error override;
#endif #endif
#if defined(__APPLE__) #if defined(__APPLE__)

View File

@ -49,9 +49,9 @@ private:
[[nodiscard]] auto get_next_handle() -> std::uint64_t; [[nodiscard]] auto get_next_handle() -> std::uint64_t;
[[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) -> packet::error_type; -> packet::error_type;
void populate_file_info(const std::string &api_path, const UINT64 &file_size, void populate_file_info(const std::string &api_path, const UINT64 &file_size,
const UINT32 &attributes, const UINT32 &attributes,
@ -72,14 +72,14 @@ public:
[[nodiscard]] auto fuse_chmod(const char *path, const remote::file_mode &mode) [[nodiscard]] auto fuse_chmod(const char *path, const remote::file_mode &mode)
-> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto fuse_chown(const char *path, const remote::user_id &uid,
fuse_chown(const char *path, const remote::user_id &uid, const remote::group_id &gid)
const remote::group_id &gid) -> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto
fuse_create(const char *path, const remote::file_mode &mode, fuse_create(const char *path, const remote::file_mode &mode,
const remote::open_flags &flags, const remote::open_flags &flags, remote::file_handle &handle)
remote::file_handle &handle) -> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto fuse_destroy() -> packet::error_type override; [[nodiscard]] auto fuse_destroy() -> packet::error_type override;
@ -88,25 +88,28 @@ public:
remote::file_offset &length, const remote::file_handle &handle) override remote::file_offset &length, const remote::file_handle &handle) override
;*/ ;*/
[[nodiscard]] auto fuse_fgetattr( [[nodiscard]] auto fuse_fgetattr(const char *path, remote::stat &r_stat,
const char *path, remote::stat &r_stat, bool &directory, bool &directory,
const remote::file_handle &handle) -> packet::error_type override; const remote::file_handle &handle)
-> packet::error_type override;
[[nodiscard]] auto fuse_fsetattr_x( [[nodiscard]] auto fuse_fsetattr_x(const char *path,
const char *path, const remote::setattr_x &attr, const remote::setattr_x &attr,
const remote::file_handle &handle) -> packet::error_type override; const remote::file_handle &handle)
-> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto fuse_fsync(const char *path, const std::int32_t &datasync,
fuse_fsync(const char *path, const std::int32_t &datasync, const remote::file_handle &handle)
const remote::file_handle &handle) -> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto fuse_ftruncate( [[nodiscard]] auto fuse_ftruncate(const char *path,
const char *path, const remote::file_offset &size, const remote::file_offset &size,
const remote::file_handle &handle) -> packet::error_type override; const remote::file_handle &handle)
-> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto fuse_getattr(const char *path, remote::stat &r_stat,
fuse_getattr(const char *path, remote::stat &r_stat, bool &directory)
bool &directory) -> packet::error_type override; -> packet::error_type override;
/*[[nodiscard]] packet::error_type fuse_getxattr(const char *path, const char /*[[nodiscard]] packet::error_type fuse_getxattr(const char *path, const char
*name, char *value, const remote::file_size &size) override ; *name, char *value, const remote::file_size &size) override ;
@ -115,9 +118,10 @@ public:
*name, char *value, const remote::file_size &size, std::uint32_t position) *name, char *value, const remote::file_size &size, std::uint32_t position)
override ;*/ override ;*/
[[nodiscard]] auto [[nodiscard]] auto fuse_getxtimes(const char *path,
fuse_getxtimes(const char *path, remote::file_time &bkuptime, remote::file_time &bkuptime,
remote::file_time &crtime) -> packet::error_type override; remote::file_time &crtime)
-> packet::error_type override;
[[nodiscard]] auto fuse_init() -> packet::error_type override; [[nodiscard]] auto fuse_init() -> packet::error_type override;
@ -125,28 +129,30 @@ public:
*buffer, const remote::file_size &size) override ;*/ *buffer, const remote::file_size &size) override ;*/
[[nodiscard]] auto [[nodiscard]] auto
fuse_mkdir(const char *path, fuse_mkdir(const char *path, const remote::file_mode &mode)
const remote::file_mode &mode) -> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto fuse_open(const char *path,
fuse_open(const char *path, const remote::open_flags &flags, const remote::open_flags &flags,
remote::file_handle &handle) -> packet::error_type override; remote::file_handle &handle)
-> packet::error_type override;
[[nodiscard]] auto fuse_opendir(const char *path, remote::file_handle &handle) [[nodiscard]] auto fuse_opendir(const char *path, remote::file_handle &handle)
-> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto fuse_read(const char *path, char *buffer,
fuse_read(const char *path, char *buffer, const remote::file_size &read_size, const remote::file_size &read_size,
const remote::file_offset &read_offset, const remote::file_offset &read_offset,
const remote::file_handle &handle) -> packet::error_type override; const remote::file_handle &handle)
-> packet::error_type override;
[[nodiscard]] auto fuse_rename(const char *from, [[nodiscard]] auto fuse_rename(const char *from, const char *to)
const char *to) -> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto
fuse_readdir(const char *path, const remote::file_offset &offset, fuse_readdir(const char *path, const remote::file_offset &offset,
const remote::file_handle &handle, const remote::file_handle &handle, std::string &item_path)
std::string &item_path) -> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto fuse_release(const char *path, [[nodiscard]] auto fuse_release(const char *path,
const remote::file_handle &handle) const remote::file_handle &handle)
@ -160,8 +166,8 @@ public:
* char *name) override * char *name) override
* ;*/ * ;*/
[[nodiscard]] auto [[nodiscard]] auto fuse_rmdir(const char *path)
fuse_rmdir(const char *path) -> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto fuse_setattr_x(const char *path, remote::setattr_x &attr) [[nodiscard]] auto fuse_setattr_x(const char *path, remote::setattr_x &attr)
-> packet::error_type override; -> packet::error_type override;
@ -178,8 +184,8 @@ public:
const remote::file_time &crtime) const remote::file_time &crtime)
-> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto fuse_setvolname(const char *volname)
fuse_setvolname(const char *volname) -> packet::error_type override; -> packet::error_type override;
/*[[nodiscard]] packet::error_type fuse_setxattr(const char *path, const char /*[[nodiscard]] packet::error_type fuse_setxattr(const char *path, const char
*name, const char *value, const remote::file_size &size, const std::int32_t *name, const char *value, const remote::file_size &size, const std::int32_t
@ -189,67 +195,70 @@ public:
char *name, const char *value, const remote::file_size &size, const char *name, const char *value, const remote::file_size &size, const
std::int32_t &flags, std::uint32_t position) override ;*/ std::int32_t &flags, std::uint32_t position) override ;*/
[[nodiscard]] auto [[nodiscard]] auto fuse_statfs(const char *path, std::uint64_t frsize,
fuse_statfs(const char *path, std::uint64_t frsize, remote::statfs &r_stat)
remote::statfs &r_stat) -> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto fuse_statfs_x(const char *path, std::uint64_t bsize,
fuse_statfs_x(const char *path, std::uint64_t bsize, remote::statfs_x &r_stat)
remote::statfs_x &r_stat) -> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto fuse_truncate(const char *path,
fuse_truncate(const char *path, const remote::file_offset &size)
const remote::file_offset &size) -> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto fuse_unlink(const char *path)
fuse_unlink(const char *path) -> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto fuse_utimens(const char *path, const remote::file_time *tv,
fuse_utimens(const char *path, const remote::file_time *tv, std::uint64_t op0, std::uint64_t op0, std::uint64_t op1)
std::uint64_t op1) -> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto fuse_write(const char *path, const char *buffer,
fuse_write(const char *path, const char *buffer, const remote::file_size &write_size,
const remote::file_size &write_size, const remote::file_offset &write_offset,
const remote::file_offset &write_offset, const remote::file_handle &handle)
const remote::file_handle &handle) -> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto fuse_write_base64( [[nodiscard]] auto fuse_write_base64(const char *path, const char *buffer,
const char *path, const char *buffer, const remote::file_size &write_size, const remote::file_size &write_size,
const remote::file_offset &write_offset, const remote::file_offset &write_offset,
const remote::file_handle &handle) -> packet::error_type override; const remote::file_handle &handle)
-> packet::error_type override;
void set_fuse_uid_gid(const remote::user_id &, void set_fuse_uid_gid(const remote::user_id &,
const remote::group_id &) override {} const remote::group_id &) override {}
// JSON Layer // JSON Layer
[[nodiscard]] auto [[nodiscard]] auto winfsp_get_dir_buffer(PVOID /*file_desc*/,
winfsp_get_dir_buffer(PVOID /*file_desc*/, PVOID *& /*ptr*/)
PVOID *& /*ptr*/) -> packet::error_type override { -> packet::error_type override {
return static_cast<packet::error_type>(STATUS_INVALID_HANDLE); return static_cast<packet::error_type>(STATUS_INVALID_HANDLE);
} }
[[nodiscard]] auto json_create_directory_snapshot( [[nodiscard]] auto json_create_directory_snapshot(const std::string &path,
const std::string &path, json &json_data) -> packet::error_type override; json &json_data)
-> packet::error_type override;
[[nodiscard]] auto json_read_directory_snapshot( [[nodiscard]] auto json_read_directory_snapshot(
const std::string &path, const remote::file_handle &handle, const std::string &path, const remote::file_handle &handle,
std::uint32_t page, json &json_data) -> packet::error_type override; std::uint32_t page, json &json_data) -> packet::error_type override;
[[nodiscard]] auto json_release_directory_snapshot( [[nodiscard]] auto
const std::string &path, json_release_directory_snapshot(const std::string &path,
const remote::file_handle &handle) -> packet::error_type override; const remote::file_handle &handle)
-> packet::error_type override;
// WinFSP Layer // WinFSP Layer
[[nodiscard]] auto winfsp_can_delete(PVOID file_desc, PWSTR file_name) [[nodiscard]] auto winfsp_can_delete(PVOID file_desc, PWSTR file_name)
-> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto winfsp_cleanup(PVOID file_desc, PWSTR file_name,
winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags, UINT32 flags, BOOLEAN &was_deleted)
BOOLEAN &was_closed) -> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto winfsp_close(PVOID file_desc)
winfsp_close(PVOID file_desc) -> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto
winfsp_create(PWSTR file_name, UINT32 create_options, UINT32 granted_access, winfsp_create(PWSTR file_name, UINT32 create_options, UINT32 granted_access,
@ -264,57 +273,63 @@ public:
remote::file_info *file_info) remote::file_info *file_info)
-> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto winfsp_get_security_by_name(
PWSTR file_name, PUINT32 attributes,
std::uint64_t * /*security_descriptor_size*/,
std::wstring & /*str_descriptor*/) -> packet::error_type override;
[[nodiscard]] auto winfsp_get_volume_info(
UINT64 &total_size, UINT64 &free_size,
std::string &volume_label) -> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto
winfsp_mounted(const std::wstring &location) -> packet::error_type override; winfsp_get_security_by_name(PWSTR file_name, PUINT32 attributes,
std::uint64_t * /*security_descriptor_size*/,
std::wstring & /*str_descriptor*/)
-> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto winfsp_get_volume_info(UINT64 &total_size,
winfsp_open(PWSTR file_name, UINT32 create_options, UINT32 granted_access, UINT64 &free_size,
PVOID *file_desc, remote::file_info *file_info, std::string &volume_label)
std::string &normalized_name) -> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto winfsp_mounted(const std::wstring &location)
winfsp_overwrite(PVOID file_desc, UINT32 attributes, -> packet::error_type override;
BOOLEAN replace_attributes, UINT64 /*allocation_size*/,
remote::file_info *file_info) -> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto winfsp_open(PWSTR file_name, UINT32 create_options,
winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length, UINT32 granted_access, PVOID *file_desc,
PUINT32 bytes_transferred) -> packet::error_type override; remote::file_info *file_info,
std::string &normalized_name)
-> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto winfsp_overwrite(PVOID file_desc, UINT32 attributes,
winfsp_read_directory(PVOID file_desc, PWSTR /*pattern*/, PWSTR marker, BOOLEAN replace_attributes,
json &itemList) -> packet::error_type override; UINT64 /*allocation_size*/,
remote::file_info *file_info)
-> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset,
winfsp_rename(PVOID /*file_desc*/, PWSTR file_name, PWSTR new_file_name, UINT32 length, PUINT32 bytes_transferred)
BOOLEAN replace_if_exists) -> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto winfsp_read_directory(PVOID file_desc, PWSTR /*pattern*/,
PWSTR marker, json &itemList)
-> packet::error_type override;
[[nodiscard]] auto winfsp_rename(PVOID /*file_desc*/, PWSTR file_name,
PWSTR new_file_name,
BOOLEAN replace_if_exists)
-> packet::error_type override;
[[nodiscard]] auto winfsp_set_basic_info( [[nodiscard]] auto winfsp_set_basic_info(
PVOID file_desc, UINT32 attributes, UINT64 creation_time, PVOID file_desc, UINT32 attributes, UINT64 creation_time,
UINT64 last_access_time, UINT64 last_write_time, UINT64 change_time, UINT64 last_access_time, UINT64 last_write_time, UINT64 change_time,
remote::file_info *file_info) -> packet::error_type override; remote::file_info *file_info) -> packet::error_type override;
[[nodiscard]] auto winfsp_set_file_size( [[nodiscard]] auto winfsp_set_file_size(PVOID file_desc, UINT64 new_size,
PVOID file_desc, UINT64 new_size, BOOLEAN set_allocation_size, BOOLEAN set_allocation_size,
remote::file_info *file_info) -> packet::error_type override; remote::file_info *file_info)
-> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto winfsp_unmounted(const std::wstring &location)
winfsp_unmounted(const std::wstring &location) -> packet::error_type override; -> packet::error_type override;
[[nodiscard]] auto [[nodiscard]] auto
winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length, winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
BOOLEAN write_to_end, BOOLEAN constrained_io, BOOLEAN write_to_end, BOOLEAN constrained_io,
PUINT32 bytes_transferred, PUINT32 bytes_transferred, remote::file_info *file_info)
remote::file_info *file_info) -> packet::error_type override; -> packet::error_type override;
}; };
} // namespace remote_fuse } // namespace remote_fuse
} // namespace repertory } // namespace repertory

View File

@ -33,25 +33,32 @@ protected:
virtual ~remote_open_file_table() = default; virtual ~remote_open_file_table() = default;
protected: protected:
struct compat_open_info { struct compat_open_info final {
std::size_t count{0U};
std::string client_id; std::string client_id;
std::vector<remote::file_handle> handles;
std::string path; std::string path;
}; };
struct open_info { struct open_info final {
std::size_t count{0U};
std::string client_id; std::string client_id;
PVOID directory_buffer{nullptr}; PVOID directory_buffer{nullptr};
std::vector<native_handle> handles;
std::string path; std::string path;
}; };
private: private:
std::unordered_map<remote::file_handle, compat_open_info> compat_lookup_; std::unordered_map<std::string, std::unique_ptr<compat_open_info>>
std::recursive_mutex compat_mutex_; compat_file_lookup_;
std::unordered_map<remote::file_handle, std::string> compat_handle_lookup_;
private:
std::unordered_map<std::string, std::vector<std::uint64_t>> directory_lookup_; std::unordered_map<std::string, std::vector<std::uint64_t>> directory_lookup_;
std::recursive_mutex directory_mutex_;
std::unordered_map<native_handle, open_info> file_lookup_; private:
std::unordered_map<std::string, std::unique_ptr<open_info>> file_lookup_;
std::unordered_map<native_handle, std::string> handle_lookup_;
private:
mutable std::recursive_mutex file_mutex_; mutable std::recursive_mutex file_mutex_;
protected: protected:
@ -64,11 +71,11 @@ protected:
PVOID *&buffer) -> bool; PVOID *&buffer) -> bool;
#endif // _WIN32 #endif // _WIN32
[[nodiscard]] auto [[nodiscard]] auto get_open_file_path(const native_handle &handle)
get_open_file_path(const native_handle &handle) -> std::string; -> std::string;
[[nodiscard]] auto get_open_info(const native_handle &handle, [[nodiscard]] auto get_open_info(const native_handle &handle, open_info &oi)
open_info &oi) -> bool; -> bool;
[[nodiscard]] auto has_open_directory(const std::string &client_id, [[nodiscard]] auto has_open_directory(const std::string &client_id,
std::uint64_t handle) -> bool; std::uint64_t handle) -> bool;
@ -77,20 +84,21 @@ protected:
int error_return) -> int; int error_return) -> int;
template <typename error_type> template <typename error_type>
[[nodiscard]] auto [[nodiscard]] auto has_open_info(const native_handle &handle,
has_open_info(const native_handle &handle, const error_type &error_return)
const error_type &error_return) -> error_type { -> error_type {
recur_mutex_lock file_lock(file_mutex_); recur_mutex_lock file_lock(file_mutex_);
return ((file_lookup_.find(handle) == file_lookup_.end()) ? error_return return handle_lookup_.contains(handle) ? 0 : error_return;
: 0);
} }
void remove_all(const std::string &file_path); void remove_all(const std::string &file_path);
void remove_and_close_all(const native_handle &handle);
void remove_compat_open_info(const remote::file_handle &handle); void remove_compat_open_info(const remote::file_handle &handle);
auto remove_directory(const std::string &client_id, auto remove_directory(const std::string &client_id, std::uint64_t handle)
std::uint64_t handle) -> bool; -> bool;
void remove_open_info(const native_handle &handle); void remove_open_info(const native_handle &handle);
@ -102,11 +110,11 @@ protected:
void set_compat_open_info(const remote::file_handle &handle, void set_compat_open_info(const remote::file_handle &handle,
const std::string &file_path); const std::string &file_path);
void set_open_info(const native_handle &handle, open_info oi); void set_open_info(const native_handle &handle, open_info op_info);
public: public:
[[nodiscard]] auto [[nodiscard]] auto get_open_file_count(const std::string &file_path) const
get_open_file_count(const std::string &file_path) const -> std::size_t; -> std::size_t;
}; };
} // namespace repertory } // namespace repertory

View File

@ -29,6 +29,8 @@
#include "drives/fuse/remotefuse/i_remote_instance.hpp" #include "drives/fuse/remotefuse/i_remote_instance.hpp"
#include "drives/remote/remote_open_file_table.hpp" #include "drives/remote/remote_open_file_table.hpp"
#include "drives/winfsp/remotewinfsp/i_remote_instance.hpp" #include "drives/winfsp/remotewinfsp/i_remote_instance.hpp"
#include "events/event_system.hpp"
#include "events/events.hpp"
#include "types/remote.hpp" #include "types/remote.hpp"
#include "types/repertory.hpp" #include "types/repertory.hpp"
#include "utils/base64.hpp" #include "utils/base64.hpp"
@ -52,7 +54,7 @@ public:
: config_(config), : config_(config),
drive_(drv), drive_(drv),
mount_location_(std::move(mount_location)), mount_location_(std::move(mount_location)),
client_pool_(config.get_remote_client_pool_size()) { client_pool_(config.get_remote_mount().client_pool_size) {
event_system::instance().raise<service_started>("remote_server_base"); event_system::instance().raise<service_started>("remote_server_base");
handler_lookup_.insert( handler_lookup_.insert(
{"::winfsp_can_delete", {"::winfsp_can_delete",
@ -85,10 +87,10 @@ public:
UINT32 flags{}; UINT32 flags{};
DECODE_OR_RETURN(request, flags); DECODE_OR_RETURN(request, flags);
BOOLEAN was_closed{}; BOOLEAN was_deleted{};
ret = this->winfsp_cleanup(file_desc, file_name.data(), flags, ret = this->winfsp_cleanup(file_desc, file_name.data(), flags,
was_closed); was_deleted);
response.encode(was_closed); response.encode(was_deleted);
return ret; return ret;
}}); }});
@ -137,12 +139,12 @@ public:
if (ret == STATUS_SUCCESS) { if (ret == STATUS_SUCCESS) {
#if defined(_WIN32) #if defined(_WIN32)
this->set_client_id(file_desc, client_id); this->set_client_id(file_desc, client_id);
#else #else // !defined(_WIN32)
this->set_client_id( this->set_client_id(
static_cast<native_handle>( static_cast<native_handle>(
reinterpret_cast<std::uintptr_t>(file_desc)), reinterpret_cast<std::uintptr_t>(file_desc)),
client_id); client_id);
#endif #endif // defined(_WIN32)
response.encode(file_desc); response.encode(file_desc);
response.encode(file_info); response.encode(file_info);
response.encode(normalized_name); response.encode(normalized_name);
@ -277,12 +279,12 @@ public:
if (ret == STATUS_SUCCESS) { if (ret == STATUS_SUCCESS) {
#if defined(_WIN32) #if defined(_WIN32)
this->set_client_id(file_desc, client_id); this->set_client_id(file_desc, client_id);
#else #else // !defined(_WIN32)
this->set_client_id( this->set_client_id(
static_cast<native_handle>( static_cast<native_handle>(
reinterpret_cast<std::uintptr_t>(file_desc)), reinterpret_cast<std::uintptr_t>(file_desc)),
client_id); client_id);
#endif #endif // defined(_WIN32)
response.encode(file_desc); response.encode(file_desc);
response.encode(file_info); response.encode(file_info);
response.encode(normalized_name); response.encode(normalized_name);
@ -585,9 +587,9 @@ public:
0) { 0) {
#if defined(_WIN32) #if defined(_WIN32)
this->set_compat_client_id(handle, client_id); this->set_compat_client_id(handle, client_id);
#else #else // !defined(_WIN32)
this->set_client_id(static_cast<native_handle>(handle), client_id); this->set_client_id(static_cast<native_handle>(handle), client_id);
#endif #endif // defined(_WIN32)
response.encode(handle); response.encode(handle);
} }
return ret; return ret;
@ -841,9 +843,9 @@ public:
if ((ret = this->fuse_open(path.c_str(), flags, handle)) >= 0) { if ((ret = this->fuse_open(path.c_str(), flags, handle)) >= 0) {
#if defined(_WIN32) #if defined(_WIN32)
this->set_compat_client_id(handle, client_id); this->set_compat_client_id(handle, client_id);
#else #else // !defined(_WIN32)
this->set_client_id(static_cast<native_handle>(handle), client_id); this->set_client_id(static_cast<native_handle>(handle), client_id);
#endif #endif // defined(_WIN32)
response.encode(handle); response.encode(handle);
} }
return ret; return ret;
@ -1357,7 +1359,8 @@ public:
}}); }});
packet_server_ = std::make_unique<packet_server>( packet_server_ = std::make_unique<packet_server>(
config_.get_remote_port(), config_.get_remote_token(), 10, config_.get_remote_mount().api_port,
config_.get_remote_mount().encryption_token, 10,
[this](const std::string &client_id) { [this](const std::string &client_id) {
return this->closed_handler(client_id); return this->closed_handler(client_id);
}, },

View File

@ -31,22 +31,25 @@ class i_winfsp_drive {
INTERFACE_SETUP(i_winfsp_drive); INTERFACE_SETUP(i_winfsp_drive);
public: public:
[[nodiscard]] virtual auto get_directory_item_count( [[nodiscard]] virtual auto
const std::string &api_path) const -> std::uint64_t = 0; get_directory_item_count(const std::string &api_path) const
-> std::uint64_t = 0;
[[nodiscard]] virtual auto get_directory_items(
const std::string &api_path) const -> directory_item_list = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
get_file_size(const std::string &api_path) const -> std::uint64_t = 0; get_directory_items(const std::string &api_path) const
-> directory_item_list = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto get_file_size(const std::string &api_path) const
get_item_meta(const std::string &api_path, const std::string &name, -> std::uint64_t = 0;
std::string &value) const -> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto get_item_meta(const std::string &api_path,
get_item_meta(const std::string &api_path, const std::string &name,
api_meta_map &meta) const -> api_error = 0; std::string &value) const
-> api_error = 0;
[[nodiscard]] virtual auto get_item_meta(const std::string &api_path,
api_meta_map &meta) const
-> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
get_security_by_name(PWSTR file_name, PUINT32 attributes, get_security_by_name(PWSTR file_name, PUINT32 attributes,
@ -62,9 +65,9 @@ public:
virtual void get_volume_info(UINT64 &total_size, UINT64 &free_size, virtual void get_volume_info(UINT64 &total_size, UINT64 &free_size,
std::string &volume_label) const = 0; std::string &volume_label) const = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto populate_file_info(const std::string &api_path,
populate_file_info(const std::string &api_path, remote::file_info &fi) const
remote::file_info &fi) -> api_error = 0; -> api_error = 0;
}; };
} // namespace repertory } // namespace repertory

View File

@ -29,11 +29,11 @@ class i_remote_instance : public virtual i_remote_json {
INTERFACE_SETUP(i_remote_instance); INTERFACE_SETUP(i_remote_instance);
public: public:
virtual auto winfsp_can_delete(PVOID file_desc, virtual auto winfsp_can_delete(PVOID file_desc, PWSTR file_name)
PWSTR file_name) -> packet::error_type = 0; -> packet::error_type = 0;
virtual auto winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags, virtual auto winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags,
BOOLEAN &was_closed) -> packet::error_type = 0; BOOLEAN &was_deleted) -> packet::error_type = 0;
virtual auto winfsp_close(PVOID file_desc) -> packet::error_type = 0; virtual auto winfsp_close(PVOID file_desc) -> packet::error_type = 0;
@ -41,72 +41,76 @@ public:
UINT32 granted_access, UINT32 file_attributes, UINT32 granted_access, UINT32 file_attributes,
UINT64 allocation_size, PVOID *file_desc, UINT64 allocation_size, PVOID *file_desc,
remote::file_info *file_info, remote::file_info *file_info,
std::string &normalized_name, std::string &normalized_name, BOOLEAN &exists)
BOOLEAN &exists) -> packet::error_type = 0; -> packet::error_type = 0;
virtual auto winfsp_flush(PVOID file_desc, remote::file_info *file_info) virtual auto winfsp_flush(PVOID file_desc, remote::file_info *file_info)
-> packet::error_type = 0; -> packet::error_type = 0;
virtual auto winfsp_get_dir_buffer(PVOID file_desc, virtual auto winfsp_get_dir_buffer(PVOID file_desc, PVOID *&ptr)
PVOID *&ptr) -> packet::error_type = 0; -> packet::error_type = 0;
virtual auto winfsp_get_file_info(PVOID file_desc,
remote::file_info *file_info)
-> packet::error_type = 0;
virtual auto virtual auto
winfsp_get_file_info(PVOID file_desc, winfsp_get_security_by_name(PWSTR file_name, PUINT32 file_attributes,
remote::file_info *file_info) -> packet::error_type = 0; std::uint64_t *security_descriptor_size,
std::wstring &str_descriptor)
-> packet::error_type = 0;
virtual auto winfsp_get_security_by_name( virtual auto winfsp_get_volume_info(UINT64 &total_size, UINT64 &free_size,
PWSTR file_name, PUINT32 file_attributes, std::string &volume_label)
std::uint64_t *security_descriptor_size, -> packet::error_type = 0;
std::wstring &str_descriptor) -> packet::error_type = 0;
virtual auto virtual auto winfsp_mounted(const std::wstring &location)
winfsp_get_volume_info(UINT64 &total_size, UINT64 &free_size, -> packet::error_type = 0;
std::string &volume_label) -> packet::error_type = 0;
virtual auto virtual auto winfsp_open(PWSTR file_name, UINT32 create_options,
winfsp_mounted(const std::wstring &location) -> packet::error_type = 0; UINT32 granted_access, PVOID *file_desc,
remote::file_info *file_info,
std::string &normalized_name)
-> packet::error_type = 0;
virtual auto virtual auto winfsp_overwrite(PVOID file_desc, UINT32 file_attributes,
winfsp_open(PWSTR file_name, UINT32 create_options, UINT32 granted_access, BOOLEAN replace_file_attributes,
PVOID *file_desc, remote::file_info *file_info, UINT64 allocation_size,
std::string &normalized_name) -> packet::error_type = 0; remote::file_info *file_info)
-> packet::error_type = 0;
virtual auto
winfsp_overwrite(PVOID file_desc, UINT32 file_attributes,
BOOLEAN replace_file_attributes, UINT64 allocation_size,
remote::file_info *file_info) -> packet::error_type = 0;
virtual auto winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, virtual auto winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset,
UINT32 length, UINT32 length, PUINT32 bytes_transferred)
PUINT32 bytes_transferred) -> packet::error_type = 0; -> packet::error_type = 0;
virtual auto winfsp_read_directory(PVOID file_desc, PWSTR pattern, virtual auto winfsp_read_directory(PVOID file_desc, PWSTR pattern,
PWSTR marker, PWSTR marker, json &itemList)
json &itemList) -> packet::error_type = 0; -> packet::error_type = 0;
virtual auto virtual auto winfsp_rename(PVOID file_desc, PWSTR file_name,
winfsp_rename(PVOID file_desc, PWSTR file_name, PWSTR new_file_name, PWSTR new_file_name, BOOLEAN replace_if_exists)
BOOLEAN replace_if_exists) -> packet::error_type = 0; -> packet::error_type = 0;
virtual auto virtual auto winfsp_set_basic_info(PVOID file_desc, UINT32 file_attributes,
winfsp_set_basic_info(PVOID file_desc, UINT32 file_attributes, UINT64 creation_time,
UINT64 creation_time, UINT64 last_access_time, UINT64 last_access_time,
UINT64 last_write_time, UINT64 change_time, UINT64 last_write_time, UINT64 change_time,
remote::file_info *file_info) -> packet::error_type = 0; remote::file_info *file_info)
-> packet::error_type = 0;
virtual auto virtual auto winfsp_set_file_size(PVOID file_desc, UINT64 new_size,
winfsp_set_file_size(PVOID file_desc, UINT64 new_size, BOOLEAN set_allocation_size,
BOOLEAN set_allocation_size, remote::file_info *file_info)
remote::file_info *file_info) -> packet::error_type = 0; -> packet::error_type = 0;
virtual auto virtual auto winfsp_unmounted(const std::wstring &location)
winfsp_unmounted(const std::wstring &location) -> packet::error_type = 0; -> packet::error_type = 0;
virtual auto virtual auto winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset,
winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length, UINT32 length, BOOLEAN write_to_end,
BOOLEAN write_to_end, BOOLEAN constrained_io, BOOLEAN constrained_io, PUINT32 bytes_transferred,
PUINT32 bytes_transferred, remote::file_info *file_info)
remote::file_info *file_info) -> packet::error_type = 0; -> packet::error_type = 0;
}; };
using remote_instance_factory = using remote_instance_factory =

View File

@ -50,19 +50,20 @@ public:
auto json_create_directory_snapshot(const std::string &path, json &json_data) auto json_create_directory_snapshot(const std::string &path, json &json_data)
-> packet::error_type override; -> packet::error_type override;
auto json_read_directory_snapshot( auto json_read_directory_snapshot(const std::string &path,
const std::string &path, const remote::file_handle &handle, const remote::file_handle &handle,
std::uint32_t page, json &json_data) -> packet::error_type override; std::uint32_t page, json &json_data)
-> packet::error_type override;
auto json_release_directory_snapshot(const std::string &path, auto json_release_directory_snapshot(const std::string &path,
const remote::file_handle &handle) const remote::file_handle &handle)
-> packet::error_type override; -> packet::error_type override;
auto winfsp_can_delete(PVOID file_desc, auto winfsp_can_delete(PVOID file_desc, PWSTR file_name)
PWSTR file_name) -> packet::error_type override; -> packet::error_type override;
auto winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags, auto winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags,
BOOLEAN &was_closed) -> packet::error_type override; BOOLEAN &was_deleted) -> packet::error_type override;
auto winfsp_close(PVOID file_desc) -> packet::error_type override; auto winfsp_close(PVOID file_desc) -> packet::error_type override;
@ -75,32 +76,33 @@ public:
auto winfsp_flush(PVOID file_desc, remote::file_info *file_info) auto winfsp_flush(PVOID file_desc, remote::file_info *file_info)
-> packet::error_type override; -> packet::error_type override;
auto winfsp_get_dir_buffer(PVOID file_desc, auto winfsp_get_dir_buffer(PVOID file_desc, PVOID *&ptr)
PVOID *&ptr) -> packet::error_type override; -> packet::error_type override;
auto winfsp_get_file_info(PVOID file_desc, remote::file_info *file_info) auto winfsp_get_file_info(PVOID file_desc, remote::file_info *file_info)
-> packet::error_type override; -> packet::error_type override;
auto winfsp_get_security_by_name( auto winfsp_get_security_by_name(PWSTR file_name, PUINT32 attributes,
PWSTR file_name, PUINT32 attributes, std::uint64_t *descriptor_size, std::uint64_t *descriptor_size,
std::wstring &string_descriptor) -> packet::error_type override; std::wstring &string_descriptor)
-> packet::error_type override;
auto winfsp_get_volume_info(UINT64 &total_size, UINT64 &free_size, auto winfsp_get_volume_info(UINT64 &total_size, UINT64 &free_size,
std::string &volume_label) std::string &volume_label)
-> packet::error_type override; -> packet::error_type override;
auto auto winfsp_mounted(const std::wstring &location)
winfsp_mounted(const std::wstring &location) -> packet::error_type override; -> packet::error_type override;
auto winfsp_open(PWSTR file_name, UINT32 create_options, auto winfsp_open(PWSTR file_name, UINT32 create_options,
UINT32 granted_access, PVOID *file_desc, UINT32 granted_access, PVOID *file_desc,
remote::file_info *file_info, remote::file_info *file_info, std::string &normalized_name)
std::string &normalized_name) -> packet::error_type override; -> packet::error_type override;
auto auto winfsp_overwrite(PVOID file_desc, UINT32 attributes,
winfsp_overwrite(PVOID file_desc, UINT32 attributes, BOOLEAN replace_attributes, UINT64 allocation_size,
BOOLEAN replace_attributes, UINT64 allocation_size, remote::file_info *file_info)
remote::file_info *file_info) -> packet::error_type override; -> packet::error_type override;
auto winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length, auto winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
PUINT32 bytes_transferred) -> packet::error_type override; PUINT32 bytes_transferred) -> packet::error_type override;
@ -111,23 +113,24 @@ public:
auto winfsp_rename(PVOID file_desc, PWSTR file_name, PWSTR new_file_name, auto winfsp_rename(PVOID file_desc, PWSTR file_name, PWSTR new_file_name,
BOOLEAN replace_if_exists) -> packet::error_type override; BOOLEAN replace_if_exists) -> packet::error_type override;
auto winfsp_set_basic_info( auto winfsp_set_basic_info(PVOID file_desc, UINT32 attributes,
PVOID file_desc, UINT32 attributes, UINT64 creation_time, UINT64 creation_time, UINT64 last_access_time,
UINT64 last_access_time, UINT64 last_write_time, UINT64 change_time, UINT64 last_write_time, UINT64 change_time,
remote::file_info *file_info) -> packet::error_type override; remote::file_info *file_info)
-> packet::error_type override;
auto winfsp_set_file_size( auto winfsp_set_file_size(PVOID file_desc, UINT64 new_size,
PVOID file_desc, UINT64 new_size, BOOLEAN set_allocation_size, BOOLEAN set_allocation_size,
remote::file_info *file_info) -> packet::error_type override; remote::file_info *file_info)
-> packet::error_type override;
auto auto winfsp_unmounted(const std::wstring &location)
winfsp_unmounted(const std::wstring &location) -> packet::error_type override; -> packet::error_type override;
auto auto winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length, BOOLEAN write_to_end, BOOLEAN constrained_io,
BOOLEAN write_to_end, BOOLEAN constrained_io, PUINT32 bytes_transferred, remote::file_info *file_info)
PUINT32 bytes_transferred, -> packet::error_type override;
remote::file_info *file_info) -> packet::error_type override;
}; };
} // namespace remote_winfsp } // namespace remote_winfsp
} // namespace repertory } // namespace repertory

View File

@ -49,23 +49,23 @@ private:
[[nodiscard]] auto get_next_handle() -> std::uint64_t; [[nodiscard]] auto get_next_handle() -> std::uint64_t;
[[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) -> packet::error_type; -> packet::error_type;
void populate_stat(const char *path, bool directory, remote::stat &r_stat, void populate_stat(const char *path, bool directory, remote::stat &r_stat,
const struct _stat64 &unix_st); const struct _stat64 &unix_st);
public: public:
// FUSE Layer // FUSE Layer
auto fuse_access(const char *path, auto fuse_access(const char *path, const std::int32_t &mask)
const std::int32_t &mask) -> packet::error_type override; -> packet::error_type override;
auto fuse_chflags(const char *path, auto fuse_chflags(const char *path, std::uint32_t flags)
std::uint32_t flags) -> packet::error_type override; -> packet::error_type override;
auto fuse_chmod(const char *path, auto fuse_chmod(const char *path, const remote::file_mode &mode)
const remote::file_mode &mode) -> packet::error_type override; -> packet::error_type override;
auto fuse_chown(const char *path, const remote::user_id &uid, auto fuse_chown(const char *path, const remote::user_id &uid,
const remote::group_id &gid) -> packet::error_type override; const remote::group_id &gid) -> packet::error_type override;
@ -84,16 +84,16 @@ public:
const remote::file_handle &handle) const remote::file_handle &handle)
-> packet::error_type override; -> packet::error_type override;
auto auto fuse_fsync(const char *path, const std::int32_t &datasync,
fuse_fsync(const char *path, const std::int32_t &datasync, const remote::file_handle &handle)
const remote::file_handle &handle) -> packet::error_type override; -> packet::error_type override;
auto fuse_ftruncate(const char *path, const remote::file_offset &size, auto fuse_ftruncate(const char *path, const remote::file_offset &size,
const remote::file_handle &handle) const remote::file_handle &handle)
-> packet::error_type override; -> packet::error_type override;
auto fuse_getattr(const char *path, remote::stat &r_stat, auto fuse_getattr(const char *path, remote::stat &r_stat, bool &directory)
bool &directory) -> packet::error_type override; -> packet::error_type override;
/*packet::error_type fuse_getxattr(const char *path, const char *name, char /*packet::error_type fuse_getxattr(const char *path, const char *name, char
*value, const remote::file_size &size) override ; *value, const remote::file_size &size) override ;
@ -110,41 +110,43 @@ public:
const remote::file_size &size) override const remote::file_size &size) override
;*/ ;*/
auto fuse_mkdir(const char *path, auto fuse_mkdir(const char *path, const remote::file_mode &mode)
const remote::file_mode &mode) -> packet::error_type override; -> packet::error_type override;
auto fuse_opendir(const char *path, auto fuse_opendir(const char *path, remote::file_handle &handle)
remote::file_handle &handle) -> packet::error_type override; -> packet::error_type override;
auto fuse_create(const char *path, const remote::file_mode &mode, auto fuse_create(const char *path, const remote::file_mode &mode,
const remote::open_flags &flags, const remote::open_flags &flags, remote::file_handle &handle)
remote::file_handle &handle) -> packet::error_type override; -> packet::error_type override;
auto fuse_open(const char *path, const remote::open_flags &flags, auto fuse_open(const char *path, const remote::open_flags &flags,
remote::file_handle &handle) -> packet::error_type override; remote::file_handle &handle) -> packet::error_type override;
auto auto fuse_read(const char *path, char *buffer,
fuse_read(const char *path, char *buffer, const remote::file_size &read_size, const remote::file_size &read_size,
const remote::file_offset &read_offset, const remote::file_offset &read_offset,
const remote::file_handle &handle) -> packet::error_type override; const remote::file_handle &handle)
-> packet::error_type override;
auto fuse_rename(const char *from, auto fuse_rename(const char *from, const char *to)
const char *to) -> packet::error_type override; -> packet::error_type override;
auto auto fuse_write(const char *path, const char *buffer,
fuse_write(const char *path, const char *buffer, const remote::file_size &write_size,
const remote::file_size &write_size, const remote::file_offset &write_offset,
const remote::file_offset &write_offset, const remote::file_handle &handle)
const remote::file_handle &handle) -> packet::error_type override; -> packet::error_type override;
auto fuse_write_base64( auto fuse_write_base64(const char *path, const char *buffer,
const char *path, const char *buffer, const remote::file_size &write_size, const remote::file_size &write_size,
const remote::file_offset &write_offset, const remote::file_offset &write_offset,
const remote::file_handle &handle) -> packet::error_type override; const remote::file_handle &handle)
-> packet::error_type override;
auto fuse_readdir(const char *path, const remote::file_offset &offset, auto fuse_readdir(const char *path, const remote::file_offset &offset,
const remote::file_handle &handle, const remote::file_handle &handle, std::string &item_path)
std::string &item_path) -> packet::error_type override; -> packet::error_type override;
auto fuse_release(const char *path, const remote::file_handle &handle) auto fuse_release(const char *path, const remote::file_handle &handle)
-> packet::error_type override; -> packet::error_type override;
@ -157,8 +159,8 @@ public:
auto fuse_rmdir(const char *path) -> packet::error_type override; auto fuse_rmdir(const char *path) -> packet::error_type override;
auto fuse_setattr_x(const char *path, auto fuse_setattr_x(const char *path, remote::setattr_x &attr)
remote::setattr_x &attr) -> packet::error_type override; -> packet::error_type override;
auto fuse_setbkuptime(const char *path, const remote::file_time &bkuptime) auto fuse_setbkuptime(const char *path, const remote::file_time &bkuptime)
-> packet::error_type override; -> packet::error_type override;
@ -191,8 +193,8 @@ public:
auto fuse_unlink(const char *path) -> packet::error_type override; auto fuse_unlink(const char *path) -> packet::error_type override;
auto fuse_utimens(const char *path, const remote::file_time *tv, auto fuse_utimens(const char *path, const remote::file_time *tv,
std::uint64_t op0, std::uint64_t op0, std::uint64_t op1)
std::uint64_t op1) -> packet::error_type override; -> packet::error_type override;
void set_fuse_uid_gid(const remote::user_id & /* uid */, void set_fuse_uid_gid(const remote::user_id & /* uid */,
const remote::group_id & /* gid */) override {} const remote::group_id & /* gid */) override {}
@ -201,20 +203,21 @@ public:
auto json_create_directory_snapshot(const std::string &path, json &json_data) auto json_create_directory_snapshot(const std::string &path, json &json_data)
-> packet::error_type override; -> packet::error_type override;
auto json_read_directory_snapshot( auto json_read_directory_snapshot(const std::string &path,
const std::string &path, const remote::file_handle &handle, const remote::file_handle &handle,
std::uint32_t page, json &json_data) -> packet::error_type override; std::uint32_t page, json &json_data)
-> packet::error_type override;
auto json_release_directory_snapshot(const std::string &path, auto json_release_directory_snapshot(const std::string &path,
const remote::file_handle &handle) const remote::file_handle &handle)
-> packet::error_type override; -> packet::error_type override;
// WinFSP Layer // WinFSP Layer
auto winfsp_can_delete(PVOID file_desc, auto winfsp_can_delete(PVOID file_desc, PWSTR file_name)
PWSTR file_name) -> packet::error_type override; -> packet::error_type override;
auto winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags, auto winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags,
BOOLEAN &was_closed) -> packet::error_type override; BOOLEAN &was_deleted) -> packet::error_type override;
auto winfsp_close(PVOID file_desc) -> packet::error_type override; auto winfsp_close(PVOID file_desc) -> packet::error_type override;
@ -227,32 +230,33 @@ public:
auto winfsp_flush(PVOID file_desc, remote::file_info *file_info) auto winfsp_flush(PVOID file_desc, remote::file_info *file_info)
-> packet::error_type override; -> packet::error_type override;
auto winfsp_get_dir_buffer(PVOID file_desc, auto winfsp_get_dir_buffer(PVOID file_desc, PVOID *&ptr)
PVOID *&ptr) -> packet::error_type override; -> packet::error_type override;
auto winfsp_get_file_info(PVOID file_desc, remote::file_info *file_info) auto winfsp_get_file_info(PVOID file_desc, remote::file_info *file_info)
-> packet::error_type override; -> packet::error_type override;
auto winfsp_get_security_by_name( auto winfsp_get_security_by_name(PWSTR file_name, PUINT32 attributes,
PWSTR file_name, PUINT32 attributes, std::uint64_t *descriptor_size, std::uint64_t *descriptor_size,
std::wstring &string_descriptor) -> packet::error_type override; std::wstring &string_descriptor)
-> packet::error_type override;
auto winfsp_get_volume_info(UINT64 &total_size, UINT64 &free_size, auto winfsp_get_volume_info(UINT64 &total_size, UINT64 &free_size,
std::string &volume_label) std::string &volume_label)
-> packet::error_type override; -> packet::error_type override;
auto auto winfsp_mounted(const std::wstring &location)
winfsp_mounted(const std::wstring &location) -> packet::error_type override; -> packet::error_type override;
auto winfsp_open(PWSTR file_name, UINT32 create_options, auto winfsp_open(PWSTR file_name, UINT32 create_options,
UINT32 granted_access, PVOID *file_desc, UINT32 granted_access, PVOID *file_desc,
remote::file_info *file_info, remote::file_info *file_info, std::string &normalized_name)
std::string &normalized_name) -> packet::error_type override; -> packet::error_type override;
auto auto winfsp_overwrite(PVOID file_desc, UINT32 attributes,
winfsp_overwrite(PVOID file_desc, UINT32 attributes, BOOLEAN replace_attributes, UINT64 allocation_size,
BOOLEAN replace_attributes, UINT64 allocation_size, remote::file_info *file_info)
remote::file_info *file_info) -> packet::error_type override; -> packet::error_type override;
auto winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length, auto winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
PUINT32 bytes_transferred) -> packet::error_type override; PUINT32 bytes_transferred) -> packet::error_type override;
@ -263,23 +267,24 @@ public:
auto winfsp_rename(PVOID file_desc, PWSTR file_name, PWSTR new_file_name, auto winfsp_rename(PVOID file_desc, PWSTR file_name, PWSTR new_file_name,
BOOLEAN replace_if_exists) -> packet::error_type override; BOOLEAN replace_if_exists) -> packet::error_type override;
auto winfsp_set_basic_info( auto winfsp_set_basic_info(PVOID file_desc, UINT32 attributes,
PVOID file_desc, UINT32 attributes, UINT64 creation_time, UINT64 creation_time, UINT64 last_access_time,
UINT64 last_access_time, UINT64 last_write_time, UINT64 change_time, UINT64 last_write_time, UINT64 change_time,
remote::file_info *file_info) -> packet::error_type override; remote::file_info *file_info)
-> packet::error_type override;
auto winfsp_set_file_size( auto winfsp_set_file_size(PVOID file_desc, UINT64 new_size,
PVOID file_desc, UINT64 new_size, BOOLEAN set_allocation_size, BOOLEAN set_allocation_size,
remote::file_info *file_info) -> packet::error_type override; remote::file_info *file_info)
-> packet::error_type override;
auto auto winfsp_unmounted(const std::wstring &location)
winfsp_unmounted(const std::wstring &location) -> packet::error_type override; -> packet::error_type override;
auto auto winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length, BOOLEAN write_to_end, BOOLEAN constrained_io,
BOOLEAN write_to_end, BOOLEAN constrained_io, PUINT32 bytes_transferred, remote::file_info *file_info)
PUINT32 bytes_transferred, -> packet::error_type override;
remote::file_info *file_info) -> packet::error_type override;
}; };
} // namespace remote_winfsp } // namespace remote_winfsp
} // namespace repertory } // namespace repertory

View File

@ -50,10 +50,10 @@ public:
private: private:
app_config &config_; app_config &config_;
lock_data &lock_;
remote_winfsp_drive &drive_; remote_winfsp_drive &drive_;
const std::vector<std::string> drive_args_; const std::vector<std::string> drive_args_;
FileSystemHost host_; FileSystemHost host_;
lock_data &lock_;
protected: protected:
auto OnStart(ULONG, PWSTR *) -> NTSTATUS override; auto OnStart(ULONG, PWSTR *) -> NTSTATUS override;
@ -75,8 +75,8 @@ private:
static void set_file_info(FileInfo &dest, const remote::file_info &src); static void set_file_info(FileInfo &dest, const remote::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;
@ -88,11 +88,11 @@ 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;
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;
auto GetSecurityByName(PWSTR file_name, PUINT32 attributes, auto GetSecurityByName(PWSTR file_name, PUINT32 attributes,
PSECURITY_DESCRIPTOR descriptor, PSECURITY_DESCRIPTOR descriptor,
@ -107,8 +107,8 @@ 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,
@ -122,8 +122,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,
@ -131,15 +131,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() { ::GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); } void shutdown() { ::GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); }

View File

@ -53,11 +53,11 @@ private:
~winfsp_service() override = default; ~winfsp_service() override = default;
private: private:
lock_data &lock_;
winfsp_drive &drive_;
const std::vector<std::string> drive_args_;
FileSystemHost host_;
app_config &config_; app_config &config_;
winfsp_drive &drive_;
std::vector<std::string> drive_args_;
FileSystemHost host_;
lock_data &lock_;
protected: protected:
auto OnStart(ULONG, PWSTR *) -> NTSTATUS override; auto OnStart(ULONG, PWSTR *) -> NTSTATUS override;
@ -75,22 +75,28 @@ 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,
FSP_FSCTL_OPEN_FILE_INFO &ofi); FSP_FSCTL_OPEN_FILE_INFO &ofi) const;
void populate_file_info(std::uint64_t file_size, api_meta_map meta, void populate_file_info(std::uint64_t file_size, api_meta_map meta,
FSP_FSCTL_FILE_INFO &fi); FSP_FSCTL_FILE_INFO &fi) const;
static void set_file_info(remote::file_info &dest, static void set_file_info(remote::file_info &dest,
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) const
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();

View File

@ -32,9 +32,12 @@ enum class event_level {
trace, trace,
}; };
auto event_level_from_string(std::string level) -> event_level; [[nodiscard]] auto
event_level_from_string(std::string level,
event_level default_level = event_level::info)
-> event_level;
auto event_level_to_string(event_level level) -> std::string; [[nodiscard]] auto event_level_to_string(event_level level) -> std::string;
class event { class event {
protected: protected:
@ -72,4 +75,18 @@ public:
}; };
} // namespace repertory } // namespace repertory
NLOHMANN_JSON_NAMESPACE_BEGIN
template <> struct adl_serializer<std::atomic<repertory::event_level>> {
static void to_json(json &data,
const std::atomic<repertory::event_level> &value) {
data = repertory::event_level_to_string(value.load());
}
static void from_json(const json &data,
std::atomic<repertory::event_level> &value) {
value.store(repertory::event_level_from_string(data.get<std::string>()));
}
};
NLOHMANN_JSON_NAMESPACE_END
#endif // REPERTORY_INCLUDE_EVENTS_EVENT_HPP_ #endif // REPERTORY_INCLUDE_EVENTS_EVENT_HPP_

View File

@ -44,6 +44,7 @@ using event_consumer = event_system::event_consumer;
#define E_FROM_STRING(t) t #define E_FROM_STRING(t) t
#define E_FROM_UINT16(t) std::to_string(t) #define E_FROM_UINT16(t) std::to_string(t)
#define E_FROM_UINT64(t) std::to_string(t) #define E_FROM_UINT64(t) std::to_string(t)
#define E_FROM_DOWNLOAD_TYPE(t) download_type_to_string(t)
#define E_PROP(type, name, short_name, ts) \ #define E_PROP(type, name, short_name, ts) \
private: \ private: \

View File

@ -0,0 +1,67 @@
/*
Copyright <2018-2024> <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 REPERTORY_INCLUDE_FILE_MANAGER_CACHE_SIZE_MGR_HPP_
#define REPERTORY_INCLUDE_FILE_MANAGER_CACHE_SIZE_MGR_HPP_
#include "types/repertory.hpp"
namespace repertory {
class app_config;
class cache_size_mgr final {
public:
cache_size_mgr(const cache_size_mgr &) = delete;
cache_size_mgr(cache_size_mgr &&) = delete;
auto operator=(const cache_size_mgr &) -> cache_size_mgr & = delete;
auto operator=(cache_size_mgr &&) -> cache_size_mgr & = delete;
protected:
cache_size_mgr() = default;
~cache_size_mgr() { stop(); }
private:
static cache_size_mgr instance_;
private:
app_config *cfg_{nullptr};
std::uint64_t cache_size_{0U};
mutable std::mutex mtx_;
std::condition_variable notify_;
stop_type stop_requested_{false};
public:
[[nodiscard]] auto expand(std::uint64_t size) -> api_error;
void initialize(app_config *cfg);
[[nodiscard]] static auto instance() -> cache_size_mgr & { return instance_; }
[[nodiscard]] auto shrink(std::uint64_t size) -> api_error;
[[nodiscard]] auto size() const -> std::uint64_t;
void stop();
};
} // namespace repertory
#endif // REPERTORY_INCLUDE_FILE_MANAGER_CACHE_SIZE_MGR_HPP_

View File

@ -0,0 +1,83 @@
/*
Copyright <2018-2024> <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 REPERTORY_INCLUDE_FILE_MANAGER_DIRECT_OPEN_FILE_HPP_
#define REPERTORY_INCLUDE_FILE_MANAGER_DIRECT_OPEN_FILE_HPP_
#include "file_manager/ring_buffer_base.hpp"
#include "types/repertory.hpp"
namespace repertory {
class i_provider;
class i_upload_manager;
class direct_open_file final : public ring_buffer_base {
public:
direct_open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
filesystem_item fsi, i_provider &provider);
~direct_open_file() override;
public:
direct_open_file() = delete;
direct_open_file(const direct_open_file &) noexcept = delete;
direct_open_file(direct_open_file &&) noexcept = delete;
auto operator=(direct_open_file &&) noexcept -> direct_open_file & = delete;
auto
operator=(const direct_open_file &) noexcept -> direct_open_file & = delete;
private:
std::array<data_buffer, min_ring_size> ring_data_;
protected:
[[nodiscard]] auto on_check_start() -> bool override;
[[nodiscard]] auto
on_chunk_downloaded(std::size_t /* chunk */,
const data_buffer & /* buffer */) -> api_error override {
return api_error::success;
}
[[nodiscard]] auto
on_read_chunk(std::size_t chunk, std::size_t read_size,
std::uint64_t read_offset, data_buffer &data,
std::size_t &bytes_read) -> api_error override;
[[nodiscard]] auto use_buffer(std::size_t chunk,
std::function<api_error(data_buffer &)> func)
-> api_error override;
public:
[[nodiscard]] auto native_operation(native_operation_callback /* callback */)
-> api_error override {
return api_error::not_supported;
}
[[nodiscard]] auto native_operation(std::uint64_t /* new_file_size */,
native_operation_callback /* callback */)
-> api_error override {
return api_error::not_supported;
}
};
} // namespace repertory
#endif // REPERTORY_INCLUDE_FILE_MANAGER_DIRECT_OPEN_FILE_HPP_

View File

@ -32,23 +32,6 @@ E_SIMPLE2(download_begin, info, true,
std::string, dest_path, dest, E_FROM_STRING std::string, dest_path, dest, E_FROM_STRING
); );
E_SIMPLE5(download_chunk_begin, debug, true,
std::string, api_path, ap, E_FROM_STRING,
std::string, dest_path, dest, E_FROM_STRING,
std::size_t, chunk, chunk, E_FROM_SIZE_T,
std::size_t, total, total, E_FROM_SIZE_T,
std::size_t, complete, complete, E_FROM_SIZE_T
);
E_SIMPLE6(download_chunk_end, debug, true,
std::string, api_path, ap, E_FROM_STRING,
std::string, dest_path, dest, E_FROM_STRING,
std::size_t, chunk, chunk, E_FROM_SIZE_T,
std::size_t, total, total, E_FROM_SIZE_T,
std::size_t, complete, complete, E_FROM_SIZE_T,
api_error, result, result, E_FROM_API_FILE_ERROR
);
E_SIMPLE3(download_end, info, true, E_SIMPLE3(download_end, info, true,
std::string, api_path, ap, E_FROM_STRING, std::string, api_path, ap, E_FROM_STRING,
std::string, dest_path, dest, E_FROM_STRING, std::string, dest_path, dest, E_FROM_STRING,
@ -78,19 +61,25 @@ E_SIMPLE3(download_resume_add_failed, error, true,
std::string, error, err, E_FROM_STRING std::string, error, err, E_FROM_STRING
); );
E_SIMPLE2(download_resume_added, info, true, E_SIMPLE2(download_resume_added, debug, true,
std::string, api_path, ap, E_FROM_STRING, std::string, api_path, ap, E_FROM_STRING,
std::string, dest_path, dest, E_FROM_STRING std::string, dest_path, dest, E_FROM_STRING
); );
E_SIMPLE2(download_resume_removed, info, true, E_SIMPLE2(download_resume_removed, debug, true,
std::string, api_path, ap, E_FROM_STRING, std::string, api_path, ap, E_FROM_STRING,
std::string, dest_path, dest, E_FROM_STRING std::string, dest_path, dest, E_FROM_STRING
); );
E_SIMPLE1(item_timeout, debug, true, E_SIMPLE1(item_timeout, trace, true,
std::string, api_path, ap, E_FROM_STRING std::string, api_path, ap, E_FROM_STRING
); );
E_SIMPLE3(download_type_selected, debug, true,
std::string, api_path, ap, E_FROM_STRING,
std::string, source, src, E_FROM_STRING,
download_type, download_type, type, E_FROM_DOWNLOAD_TYPE
);
// clang-format on // clang-format on
} // namespace repertory } // namespace repertory

View File

@ -22,14 +22,14 @@
#ifndef REPERTORY_INCLUDE_FILE_MANAGER_FILE_MANAGER_HPP_ #ifndef REPERTORY_INCLUDE_FILE_MANAGER_FILE_MANAGER_HPP_
#define REPERTORY_INCLUDE_FILE_MANAGER_FILE_MANAGER_HPP_ #define REPERTORY_INCLUDE_FILE_MANAGER_FILE_MANAGER_HPP_
#include "db/i_file_mgr_db.hpp"
#include "events/event_system.hpp" #include "events/event_system.hpp"
#include "events/events.hpp" #include "events/events.hpp"
#include "file_manager/i_file_manager.hpp" #include "file_manager/i_file_manager.hpp"
#include "file_manager/i_open_file.hpp" #include "file_manager/i_open_file.hpp"
#include "file_manager/i_upload_manager.hpp" #include "file_manager/i_upload_manager.hpp"
#include "platform/platform.hpp" #include "file_manager/upload.hpp"
#include "types/repertory.hpp" #include "types/repertory.hpp"
#include "utils/db/sqlite/db_common.hpp"
#include "utils/file.hpp" #include "utils/file.hpp"
namespace repertory { namespace repertory {
@ -39,408 +39,6 @@ class i_provider;
class file_manager final : public i_file_manager, public i_upload_manager { class file_manager final : public i_file_manager, public i_upload_manager {
E_CONSUMER(); E_CONSUMER();
public:
class open_file_base : public i_closeable_open_file {
public:
open_file_base(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
filesystem_item fsi, i_provider &provider);
open_file_base(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
filesystem_item fsi,
std::map<std::uint64_t, open_file_data> open_data,
i_provider &provider);
~open_file_base() override = default;
public:
open_file_base() = delete;
open_file_base(const open_file_base &) noexcept = delete;
open_file_base(open_file_base &&) noexcept = delete;
auto operator=(open_file_base &&) noexcept -> open_file_base & = delete;
auto
operator=(const open_file_base &) noexcept -> open_file_base & = delete;
public:
class download final {
public:
download() = default;
~download() = default;
public:
download(const download &) noexcept = delete;
download(download &&) noexcept = delete;
auto operator=(download &&) noexcept -> download & = delete;
auto operator=(const download &) noexcept -> download & = delete;
private:
bool complete_{false};
api_error error_{api_error::success};
std::mutex mtx_;
std::condition_variable notify_;
public:
void notify(const api_error &err);
auto wait() -> api_error;
};
class io_item final {
public:
io_item(std::function<api_error()> action) : action_(std::move(action)) {}
~io_item() = default;
public:
io_item() = delete;
io_item(const io_item &) noexcept = delete;
io_item(io_item &&) noexcept = delete;
auto operator=(io_item &&) noexcept -> io_item & = delete;
auto operator=(const io_item &) noexcept -> io_item & = delete;
private:
std::function<api_error()> action_;
std::mutex mtx_;
std::condition_variable notify_;
std::optional<api_error> result_;
public:
void action();
[[nodiscard]] auto get_result() -> api_error;
};
protected:
std::uint64_t chunk_size_;
std::uint8_t chunk_timeout_;
filesystem_item fsi_;
std::size_t last_chunk_size_;
std::map<std::uint64_t, open_file_data> open_data_;
i_provider &provider_;
private:
api_error error_{api_error::success};
mutable std::mutex error_mtx_;
stop_type io_stop_requested_{false};
std::unique_ptr<std::thread> io_thread_;
protected:
std::unordered_map<std::size_t, std::shared_ptr<download>>
active_downloads_;
mutable std::recursive_mutex file_mtx_;
std::atomic<std::chrono::system_clock::time_point> last_access_{
std::chrono::system_clock::now()};
bool modified_{false};
std::unique_ptr<utils::file::i_file> nf_;
mutable std::mutex io_thread_mtx_;
std::condition_variable io_thread_notify_;
std::deque<std::shared_ptr<io_item>> io_thread_queue_;
bool removed_{false};
private:
void file_io_thread();
protected:
[[nodiscard]] auto do_io(std::function<api_error()> action) -> api_error;
virtual auto is_download_complete() const -> bool = 0;
void reset_timeout();
auto set_api_error(const api_error &e) -> api_error;
public:
void add(std::uint64_t handle, open_file_data ofd) override;
[[nodiscard]] auto can_close() const -> bool override;
auto close() -> bool override;
[[nodiscard]] auto get_api_error() const -> api_error;
[[nodiscard]] auto get_api_path() const -> std::string override;
[[nodiscard]] auto get_chunk_size() const -> std::size_t override {
return chunk_size_;
}
[[nodiscard]] auto get_file_size() const -> std::uint64_t override;
[[nodiscard]] auto get_filesystem_item() const -> filesystem_item override;
[[nodiscard]] auto
get_handles() const -> std::vector<std::uint64_t> override;
[[nodiscard]] auto
get_open_data() -> std::map<std::uint64_t, open_file_data> & override;
[[nodiscard]] auto get_open_data() const
-> const std::map<std::uint64_t, open_file_data> & override;
[[nodiscard]] auto
get_open_data(std::uint64_t handle) -> open_file_data & override;
[[nodiscard]] auto get_open_data(std::uint64_t handle) const
-> const open_file_data & override;
[[nodiscard]] auto get_open_file_count() const -> std::size_t override;
[[nodiscard]] auto get_source_path() const -> std::string override {
return fsi_.source_path;
}
[[nodiscard]] auto has_handle(std::uint64_t handle) const -> bool override {
return open_data_.find(handle) != open_data_.end();
}
[[nodiscard]] auto is_directory() const -> bool override {
return fsi_.directory;
}
[[nodiscard]] auto is_modified() const -> bool override;
void remove(std::uint64_t handle) override;
void set_api_path(const std::string &api_path) override;
};
class open_file final : public open_file_base {
public:
open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
filesystem_item fsi, i_provider &provider, i_upload_manager &mgr);
open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
filesystem_item fsi,
std::map<std::uint64_t, open_file_data> open_data,
i_provider &provider, i_upload_manager &mgr);
open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
filesystem_item fsi, i_provider &provider,
std::optional<boost::dynamic_bitset<>> read_state,
i_upload_manager &mgr);
private:
open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
filesystem_item fsi,
std::map<std::uint64_t, open_file_data> open_data,
i_provider &provider,
std::optional<boost::dynamic_bitset<>> read_state,
i_upload_manager &mgr);
public:
open_file() = delete;
open_file(const open_file &) noexcept = delete;
open_file(open_file &&) noexcept = delete;
auto operator=(open_file &&) noexcept -> open_file & = delete;
auto operator=(const open_file &) noexcept -> open_file & = delete;
public:
~open_file() override;
private:
i_upload_manager &mgr_;
private:
bool notified_ = false;
std::size_t read_chunk_index_{};
boost::dynamic_bitset<> read_state_;
std::unique_ptr<std::thread> reader_thread_;
std::unique_ptr<std::thread> download_thread_;
stop_type stop_requested_ = false;
private:
void download_chunk(std::size_t chunk, bool skip_active, bool should_reset);
void download_range(std::size_t start_chunk_index,
std::size_t end_chunk_index_inclusive,
bool should_reset);
void set_modified();
void update_background_reader(std::size_t read_chunk);
protected:
auto is_download_complete() const -> bool override {
return read_state_.all();
}
public:
auto close() -> bool override;
[[nodiscard]] auto
get_read_state() const -> boost::dynamic_bitset<> override;
[[nodiscard]] auto get_read_state(std::size_t chunk) const -> bool override;
[[nodiscard]] auto is_complete() const -> bool override;
auto is_write_supported() const -> bool override { return true; }
[[nodiscard]] auto
native_operation(native_operation_callback callback) -> api_error override;
[[nodiscard]] auto
native_operation(std::uint64_t new_file_size,
native_operation_callback callback) -> api_error override;
void remove(std::uint64_t handle) override;
[[nodiscard]] auto read(std::size_t read_size, std::uint64_t read_offset,
data_buffer &data) -> api_error override;
[[nodiscard]] auto
resize(std::uint64_t new_file_size) -> api_error override;
[[nodiscard]] auto write(std::uint64_t write_offset,
const data_buffer &data,
std::size_t &bytes_written) -> api_error override;
};
class ring_buffer_open_file final : public open_file_base {
public:
ring_buffer_open_file(std::string buffer_directory,
std::uint64_t chunk_size, std::uint8_t chunk_timeout,
filesystem_item fsi, i_provider &provider);
ring_buffer_open_file(std::string buffer_directory,
std::uint64_t chunk_size, std::uint8_t chunk_timeout,
filesystem_item fsi, i_provider &provider,
std::size_t ring_size);
~ring_buffer_open_file() override;
public:
ring_buffer_open_file() = delete;
ring_buffer_open_file(const ring_buffer_open_file &) noexcept = delete;
ring_buffer_open_file(ring_buffer_open_file &&) noexcept = delete;
auto operator=(ring_buffer_open_file &&) noexcept
-> ring_buffer_open_file & = delete;
auto operator=(const ring_buffer_open_file &) noexcept
-> ring_buffer_open_file & = delete;
private:
boost::dynamic_bitset<> ring_state_;
std::size_t total_chunks_;
private:
std::unique_ptr<std::thread> chunk_forward_thread_;
std::unique_ptr<std::thread> chunk_reverse_thread_;
std::condition_variable chunk_notify_;
mutable std::mutex chunk_mtx_;
std::size_t current_chunk_{};
std::size_t first_chunk_{};
std::size_t last_chunk_;
private:
auto download_chunk(std::size_t chunk) -> api_error;
void forward_reader_thread(std::size_t count);
void reverse_reader_thread(std::size_t count);
protected:
auto is_download_complete() const -> bool override;
public:
void forward(std::size_t count);
[[nodiscard]] auto get_current_chunk() const -> std::size_t {
return current_chunk_;
}
[[nodiscard]] auto get_first_chunk() const -> std::size_t {
return first_chunk_;
}
[[nodiscard]] auto get_last_chunk() const -> std::size_t {
return last_chunk_;
}
[[nodiscard]] auto
get_read_state() const -> boost::dynamic_bitset<> override;
[[nodiscard]] auto get_read_state(std::size_t chunk) const -> bool override;
[[nodiscard]] auto get_total_chunks() const -> std::size_t {
return total_chunks_;
}
[[nodiscard]] auto is_complete() const -> bool override { return true; }
auto is_write_supported() const -> bool override { return false; }
[[nodiscard]] auto
native_operation(native_operation_callback callback) -> api_error override;
[[nodiscard]] auto
native_operation(std::uint64_t,
native_operation_callback) -> api_error override {
return api_error::not_supported;
}
[[nodiscard]] auto read(std::size_t read_size, std::uint64_t read_offset,
data_buffer &data) -> api_error override;
[[nodiscard]] auto resize(std::uint64_t) -> api_error override {
return api_error::not_supported;
}
void reverse(std::size_t count);
void set(std::size_t first_chunk, std::size_t current_chunk);
void set_api_path(const std::string &api_path) override;
[[nodiscard]] auto write(std::uint64_t, const data_buffer &,
std::size_t &) -> api_error override {
return api_error::not_supported;
}
};
class upload final {
public:
upload(filesystem_item fsi, i_provider &provider);
~upload();
public:
upload() = delete;
upload(const upload &) noexcept = delete;
upload(upload &&) noexcept = delete;
auto operator=(upload &&) noexcept -> upload & = delete;
auto operator=(const upload &) noexcept -> upload & = delete;
private:
filesystem_item fsi_;
i_provider &provider_;
private:
bool cancelled_{false};
api_error error_{api_error::success};
std::unique_ptr<std::thread> thread_;
stop_type stop_requested_{false};
private:
void upload_thread();
public:
void cancel();
[[nodiscard]] auto get_api_error() const -> api_error { return error_; }
[[nodiscard]] auto get_api_path() const -> std::string {
return fsi_.api_path;
}
[[nodiscard]] auto get_source_path() const -> std::string {
return fsi_.source_path;
}
[[nodiscard]] auto is_cancelled() const -> bool { return cancelled_; }
void stop();
};
public: public:
file_manager(app_config &config, i_provider &provider); file_manager(app_config &config, i_provider &provider);
@ -458,8 +56,8 @@ private:
i_provider &provider_; i_provider &provider_;
private: private:
utils::db::sqlite::db3_t db_{nullptr}; std::unique_ptr<i_file_mgr_db> mgr_db_;
std::uint64_t next_handle_{0U}; std::atomic<std::uint64_t> next_handle_{0U};
mutable std::recursive_mutex open_file_mtx_; mutable std::recursive_mutex open_file_mtx_;
std::unordered_map<std::string, std::shared_ptr<i_closeable_open_file>> std::unordered_map<std::string, std::shared_ptr<i_closeable_open_file>>
open_file_lookup_; open_file_lookup_;
@ -470,6 +68,8 @@ private:
std::unique_ptr<std::thread> upload_thread_; std::unique_ptr<std::thread> upload_thread_;
private: private:
[[nodiscard]] auto close_all(const std::string &api_path) -> bool;
void close_timed_out_files(); void close_timed_out_files();
auto get_open_file_by_handle(std::uint64_t handle) const auto get_open_file_by_handle(std::uint64_t handle) const
@ -485,6 +85,9 @@ private:
void queue_upload(const std::string &api_path, const std::string &source_path, void queue_upload(const std::string &api_path, const std::string &source_path,
bool no_lock); bool no_lock);
void remove_resume(const std::string &api_path,
const std::string &source_path, bool no_lock);
void remove_upload(const std::string &api_path, bool no_lock); void remove_upload(const std::string &api_path, bool no_lock);
void swap_renamed_items(std::string from_api_path, std::string to_api_path, void swap_renamed_items(std::string from_api_path, std::string to_api_path,
@ -505,6 +108,11 @@ public:
void remove_resume(const std::string &api_path, void remove_resume(const std::string &api_path,
const std::string &source_path) override; const std::string &source_path) override;
static auto remove_source_and_shrink_cache(const std::string &api_path,
const std::string &source_path,
std::uint64_t file_size,
bool allocated) -> bool;
void remove_upload(const std::string &api_path) override; void remove_upload(const std::string &api_path) override;
void store_resume(const i_open_file &file) override; void store_resume(const i_open_file &file) override;
@ -512,8 +120,6 @@ public:
public: public:
void close(std::uint64_t handle); void close(std::uint64_t handle);
void close_all(const std::string &api_path);
[[nodiscard]] auto create(const std::string &api_path, api_meta_map &meta, [[nodiscard]] auto create(const std::string &api_path, api_meta_map &meta,
open_file_data ofd, std::uint64_t &handle, open_file_data ofd, std::uint64_t &handle,
std::shared_ptr<i_open_file> &file) -> api_error; std::shared_ptr<i_open_file> &file) -> api_error;
@ -533,37 +139,36 @@ public:
[[nodiscard]] auto get_open_handle_count() const -> std::size_t; [[nodiscard]] auto get_open_handle_count() const -> std::size_t;
[[nodiscard]] auto get_stored_downloads() const -> std::vector<json>; [[nodiscard]] auto get_stored_downloads() const
-> std::vector<i_file_mgr_db::resume_entry>;
[[nodiscard]] auto has_no_open_file_handles() const -> bool override; [[nodiscard]] auto has_no_open_file_handles() const -> bool override;
[[nodiscard]] auto [[nodiscard]] auto is_processing(const std::string &api_path) const
is_processing(const std::string &api_path) const -> bool override; -> bool override;
#if defined(PROJECT_TESTING) #if defined(PROJECT_TESTING)
[[nodiscard]] auto open(std::shared_ptr<i_closeable_open_file> of, [[nodiscard]] auto open(std::shared_ptr<i_closeable_open_file> of,
const open_file_data &ofd, std::uint64_t &handle, const open_file_data &ofd, std::uint64_t &handle,
std::shared_ptr<i_open_file> &file) -> api_error; std::shared_ptr<i_open_file> &file) -> api_error;
#endif #endif // defined(PROJECT_TESTING)
[[nodiscard]] auto open(const std::string &api_path, bool directory, [[nodiscard]] auto open(const std::string &api_path, bool directory,
const open_file_data &ofd, std::uint64_t &handle, const open_file_data &ofd, std::uint64_t &handle,
std::shared_ptr<i_open_file> &file) -> api_error; std::shared_ptr<i_open_file> &file) -> api_error;
[[nodiscard]] auto remove_file(const std::string &api_path) -> api_error; [[nodiscard]] auto remove_file(const std::string &api_path) -> api_error;
[[nodiscard]] auto [[nodiscard]] auto rename_directory(const std::string &from_api_path,
rename_directory(const std::string &from_api_path, const std::string &to_api_path)
const std::string &to_api_path) -> api_error; -> api_error;
[[nodiscard]] auto rename_file(const std::string &from_api_path, [[nodiscard]] auto rename_file(const std::string &from_api_path,
const std::string &to_api_path, const std::string &to_api_path, bool overwrite)
bool overwrite) -> api_error; -> api_error;
void start(); void start();
void stop(); void stop();
void update_used_space(std::uint64_t &used_space) const override;
}; };
} // namespace repertory } // namespace repertory

View File

@ -31,21 +31,20 @@ class i_file_manager {
INTERFACE_SETUP(i_file_manager); INTERFACE_SETUP(i_file_manager);
public: public:
[[nodiscard]] virtual auto [[nodiscard]] virtual auto evict_file(const std::string &api_path)
evict_file(const std::string &api_path) -> bool = 0; -> bool = 0;
[[nodiscard]] virtual auto get_directory_items(
const std::string &api_path) const -> directory_item_list = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
get_open_files() const -> std::unordered_map<std::string, std::size_t> = 0; get_directory_items(const std::string &api_path) const
-> directory_item_list = 0;
[[nodiscard]] virtual auto get_open_files() const
-> std::unordered_map<std::string, std::size_t> = 0;
[[nodiscard]] virtual auto has_no_open_file_handles() const -> bool = 0; [[nodiscard]] virtual auto has_no_open_file_handles() const -> bool = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto is_processing(const std::string &api_path) const
is_processing(const std::string &api_path) const -> bool = 0; -> bool = 0;
virtual void update_used_space(std::uint64_t &used_space) const = 0;
}; };
} // namespace repertory } // namespace repertory

View File

@ -40,30 +40,34 @@ public:
[[nodiscard]] virtual auto get_filesystem_item() const -> filesystem_item = 0; [[nodiscard]] virtual auto get_filesystem_item() const -> filesystem_item = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto get_open_data()
get_open_data() -> std::map<std::uint64_t, open_file_data> & = 0; -> std::map<std::uint64_t, open_file_data> & = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto get_open_data() const
get_open_data() const -> const std::map<std::uint64_t, open_file_data> & = 0; -> const std::map<std::uint64_t, open_file_data> & = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto get_open_data(std::uint64_t handle)
get_open_data(std::uint64_t handle) -> open_file_data & = 0; -> open_file_data & = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto get_open_data(std::uint64_t handle) const
get_open_data(std::uint64_t handle) const -> const open_file_data & = 0; -> const open_file_data & = 0;
[[nodiscard]] virtual auto get_open_file_count() const -> std::size_t = 0; [[nodiscard]] virtual auto get_open_file_count() const -> std::size_t = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto get_read_state() const
get_read_state() const -> boost::dynamic_bitset<> = 0; -> boost::dynamic_bitset<> = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto get_read_state(std::size_t chunk) const
get_read_state(std::size_t chunk) const -> bool = 0; -> bool = 0;
[[nodiscard]] virtual auto get_source_path() const -> std::string = 0; [[nodiscard]] virtual auto get_source_path() const -> std::string = 0;
[[nodiscard]] virtual auto is_complete() const -> bool = 0;
[[nodiscard]] virtual auto is_directory() const -> bool = 0; [[nodiscard]] virtual auto is_directory() const -> bool = 0;
[[nodiscard]] virtual auto is_write_supported() const -> bool = 0;
[[nodiscard]] virtual auto has_handle(std::uint64_t handle) const -> bool = 0; [[nodiscard]] virtual auto has_handle(std::uint64_t handle) const -> bool = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
@ -74,11 +78,11 @@ public:
native_operation_callback callback) -> api_error = 0; native_operation_callback callback) -> api_error = 0;
[[nodiscard]] virtual auto read(std::size_t read_size, [[nodiscard]] virtual auto read(std::size_t read_size,
std::uint64_t read_offset, std::uint64_t read_offset, data_buffer &data)
data_buffer &data) -> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto resize(std::uint64_t new_file_size)
resize(std::uint64_t new_file_size) -> api_error = 0; -> api_error = 0;
virtual void set_api_path(const std::string &api_path) = 0; virtual void set_api_path(const std::string &api_path) = 0;
@ -93,20 +97,20 @@ class i_closeable_open_file : public i_open_file {
public: public:
virtual void add(std::uint64_t handle, open_file_data ofd) = 0; virtual void add(std::uint64_t handle, open_file_data ofd) = 0;
[[nodiscard]] virtual auto get_allocated() const -> bool = 0;
[[nodiscard]] virtual auto can_close() const -> bool = 0; [[nodiscard]] virtual auto can_close() const -> bool = 0;
virtual auto close() -> bool = 0; virtual auto close() -> bool = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto get_handles() const
get_handles() const -> std::vector<std::uint64_t> = 0; -> std::vector<std::uint64_t> = 0;
[[nodiscard]] virtual auto is_complete() const -> bool = 0;
[[nodiscard]] virtual auto is_modified() const -> bool = 0; [[nodiscard]] virtual auto is_modified() const -> bool = 0;
[[nodiscard]] virtual auto is_write_supported() const -> bool = 0;
virtual void remove(std::uint64_t handle) = 0; virtual void remove(std::uint64_t handle) = 0;
virtual void remove_all() = 0;
}; };
} // namespace repertory } // namespace repertory

View File

@ -29,14 +29,14 @@ class i_upload_manager {
INTERFACE_SETUP(i_upload_manager); INTERFACE_SETUP(i_upload_manager);
public: public:
virtual void queue_upload(const i_open_file &o) = 0; virtual void queue_upload(const i_open_file &file) = 0;
virtual void remove_resume(const std::string &api_path, virtual void remove_resume(const std::string &api_path,
const std::string &source_path) = 0; const std::string &source_path) = 0;
virtual void remove_upload(const std::string &api_path) = 0; virtual void remove_upload(const std::string &api_path) = 0;
virtual void store_resume(const i_open_file &o) = 0; virtual void store_resume(const i_open_file &file) = 0;
}; };
} // namespace repertory } // namespace repertory

View File

@ -0,0 +1,135 @@
/*
Copyright <2018-2024> <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 REPERTORY_INCLUDE_FILE_MANAGER_OPEN_FILE_HPP_
#define REPERTORY_INCLUDE_FILE_MANAGER_OPEN_FILE_HPP_
#include "file_manager/open_file_base.hpp"
#include "types/repertory.hpp"
#include "utils/types/file/i_file.hpp"
namespace repertory {
class i_provider;
class i_upload_manager;
class open_file final : public open_file_base {
public:
open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
filesystem_item fsi, i_provider &provider, i_upload_manager &mgr);
open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
filesystem_item fsi,
std::map<std::uint64_t, open_file_data> open_data,
i_provider &provider, i_upload_manager &mgr);
open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
filesystem_item fsi, i_provider &provider,
std::optional<boost::dynamic_bitset<>> read_state,
i_upload_manager &mgr);
private:
open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
filesystem_item fsi,
std::map<std::uint64_t, open_file_data> open_data,
i_provider &provider,
std::optional<boost::dynamic_bitset<>> read_state,
i_upload_manager &mgr);
public:
open_file() = delete;
open_file(const open_file &) noexcept = delete;
open_file(open_file &&) noexcept = delete;
auto operator=(open_file &&) noexcept -> open_file & = delete;
auto operator=(const open_file &) noexcept -> open_file & = delete;
public:
~open_file() override;
private:
i_upload_manager &mgr_;
private:
bool allocated{false};
std::unique_ptr<utils::file::i_file> nf_;
bool notified_{false};
std::size_t read_chunk_{};
boost::dynamic_bitset<> read_state_;
std::unique_ptr<std::thread> reader_thread_;
mutable std::recursive_mutex rw_mtx_;
stop_type stop_requested_{false};
private:
[[nodiscard]] auto adjust_cache_size(std::uint64_t file_size,
bool shrink) -> api_error;
[[nodiscard]] auto check_start() -> api_error;
void download_chunk(std::size_t chunk, bool skip_active, bool should_reset);
void download_range(std::size_t begin_chunk, std::size_t end_chunk,
bool should_reset);
void set_modified();
void set_read_state(std::size_t chunk);
void set_read_state(boost::dynamic_bitset<> read_state);
void update_reader(std::size_t chunk);
public:
auto close() -> bool override;
[[nodiscard]] auto get_allocated() const -> bool override;
[[nodiscard]] auto get_read_state() const -> boost::dynamic_bitset<> override;
[[nodiscard]] auto get_read_state(std::size_t chunk) const -> bool override;
[[nodiscard]] auto is_complete() const -> bool override;
[[nodiscard]] auto is_write_supported() const -> bool override {
return true;
}
[[nodiscard]] auto
native_operation(native_operation_callback callback) -> api_error override;
[[nodiscard]] auto
native_operation(std::uint64_t new_file_size,
native_operation_callback callback) -> api_error override;
void remove(std::uint64_t handle) override;
void remove_all() override;
[[nodiscard]] auto read(std::size_t read_size, std::uint64_t read_offset,
data_buffer &data) -> api_error override;
[[nodiscard]] auto resize(std::uint64_t new_file_size) -> api_error override;
[[nodiscard]] auto write(std::uint64_t write_offset, const data_buffer &data,
std::size_t &bytes_written) -> api_error override;
};
} // namespace repertory
#endif // REPERTORY_INCLUDE_FILE_MANAGER_OPEN_FILE_HPP_

View File

@ -0,0 +1,221 @@
/*
Copyright <2018-2024> <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 REPERTORY_INCLUDE_FILE_MANAGER_OPEN_FILE_BASE_HPP_
#define REPERTORY_INCLUDE_FILE_MANAGER_OPEN_FILE_BASE_HPP_
#include "file_manager/i_open_file.hpp"
namespace repertory {
class i_provider;
class open_file_base : public i_closeable_open_file {
public:
open_file_base(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
filesystem_item fsi, i_provider &provider, bool disable_io);
open_file_base(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
filesystem_item fsi,
std::map<std::uint64_t, open_file_data> open_data,
i_provider &provider, bool disable_io);
~open_file_base() override = default;
public:
open_file_base() = delete;
open_file_base(const open_file_base &) noexcept = delete;
open_file_base(open_file_base &&) noexcept = delete;
auto operator=(open_file_base &&) noexcept -> open_file_base & = delete;
auto operator=(const open_file_base &) noexcept -> open_file_base & = delete;
public:
class download final {
public:
download() = default;
~download() = default;
public:
download(const download &) noexcept = delete;
download(download &&) noexcept = delete;
auto operator=(download &&) noexcept -> download & = delete;
auto operator=(const download &) noexcept -> download & = delete;
private:
bool complete_{false};
api_error error_{api_error::success};
std::mutex mtx_;
std::condition_variable notify_;
public:
void notify(const api_error &err);
auto wait() -> api_error;
};
class io_item final {
public:
io_item(std::function<api_error()> action) : action_(std::move(action)) {}
~io_item() = default;
public:
io_item() = delete;
io_item(const io_item &) noexcept = delete;
io_item(io_item &&) noexcept = delete;
auto operator=(io_item &&) noexcept -> io_item & = delete;
auto operator=(const io_item &) noexcept -> io_item & = delete;
private:
std::function<api_error()> action_;
std::mutex mtx_;
std::condition_variable notify_;
std::optional<api_error> result_;
public:
void action();
[[nodiscard]] auto get_result() -> api_error;
};
private:
std::uint64_t chunk_size_;
std::uint8_t chunk_timeout_;
filesystem_item fsi_;
std::size_t last_chunk_size_;
std::map<std::uint64_t, open_file_data> open_data_;
i_provider &provider_;
private:
std::unordered_map<std::size_t, std::shared_ptr<download>> active_downloads_;
api_error error_{api_error::success};
mutable std::mutex error_mtx_;
mutable std::recursive_mutex file_mtx_;
stop_type io_stop_requested_{false};
std::unique_ptr<std::thread> io_thread_;
mutable std::mutex io_thread_mtx_;
std::condition_variable io_thread_notify_;
std::deque<std::shared_ptr<io_item>> io_thread_queue_;
std::atomic<std::chrono::system_clock::time_point> last_access_{
std::chrono::system_clock::now(),
};
bool modified_{false};
bool removed_{false};
private:
void file_io_thread();
protected:
[[nodiscard]] auto do_io(std::function<api_error()> action) -> api_error;
[[nodiscard]] auto get_active_downloads()
-> std::unordered_map<std::size_t, std::shared_ptr<download>> & {
return active_downloads_;
}
[[nodiscard]] auto get_mutex() const -> std::recursive_mutex & {
return file_mtx_;
}
[[nodiscard]] auto get_last_chunk_size() const -> std::size_t;
[[nodiscard]] auto get_provider() -> i_provider & { return provider_; }
[[nodiscard]] auto get_provider() const -> const i_provider & {
return provider_;
}
[[nodiscard]] auto is_removed() const -> bool;
void notify_io();
void reset_timeout();
auto set_api_error(const api_error &err) -> api_error;
void set_file_size(std::uint64_t size);
void set_last_chunk_size(std::size_t size);
void set_modified(bool modified);
void set_removed(bool removed);
void set_source_path(std::string source_path);
void wait_for_io(stop_type &stop_requested);
public:
void add(std::uint64_t handle, open_file_data ofd) override;
[[nodiscard]] auto can_close() const -> bool override;
auto close() -> bool override;
[[nodiscard]] auto get_allocated() const -> bool override { return false; }
[[nodiscard]] auto get_api_error() const -> api_error;
[[nodiscard]] auto get_api_path() const -> std::string override;
[[nodiscard]] auto get_chunk_size() const -> std::size_t override {
return chunk_size_;
}
[[nodiscard]] auto get_file_size() const -> std::uint64_t override;
[[nodiscard]] auto get_filesystem_item() const -> filesystem_item override;
[[nodiscard]] auto get_handles() const -> std::vector<std::uint64_t> override;
[[nodiscard]] auto
get_open_data() -> std::map<std::uint64_t, open_file_data> & override;
[[nodiscard]] auto get_open_data() const
-> const std::map<std::uint64_t, open_file_data> & override;
[[nodiscard]] auto
get_open_data(std::uint64_t handle) -> open_file_data & override;
[[nodiscard]] auto
get_open_data(std::uint64_t handle) const -> const open_file_data & override;
[[nodiscard]] auto get_open_file_count() const -> std::size_t override;
[[nodiscard]] auto get_source_path() const -> std::string override;
[[nodiscard]] auto has_handle(std::uint64_t handle) const -> bool override;
[[nodiscard]] auto is_directory() const -> bool override {
return fsi_.directory;
}
[[nodiscard]] auto is_modified() const -> bool override;
void remove(std::uint64_t handle) override;
void remove_all() override;
void set_api_path(const std::string &api_path) override;
};
} // namespace repertory
#endif // REPERTORY_INCLUDE_FILE_MANAGER_OPEN_FILE_BASE_HPP_

View File

@ -0,0 +1,150 @@
/*
Copyright <2018-2024> <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 REPERTORY_INCLUDE_FILE_MANAGER_RING_BUFFER_BASE_HPP_
#define REPERTORY_INCLUDE_FILE_MANAGER_RING_BUFFER_BASE_HPP_
#include "file_manager/open_file_base.hpp"
#include "types/repertory.hpp"
#include "utils/file.hpp"
namespace repertory {
class i_provider;
class i_upload_manager;
class ring_buffer_base : public open_file_base {
public:
ring_buffer_base(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
filesystem_item fsi, i_provider &provider,
std::size_t ring_size, bool disable_io);
~ring_buffer_base() override = default;
public:
ring_buffer_base() = delete;
ring_buffer_base(const ring_buffer_base &) noexcept = delete;
ring_buffer_base(ring_buffer_base &&) noexcept = delete;
auto operator=(ring_buffer_base &&) noexcept -> ring_buffer_base & = delete;
auto
operator=(const ring_buffer_base &) noexcept -> ring_buffer_base & = delete;
public:
static constexpr const auto min_ring_size{5U};
private:
boost::dynamic_bitset<> read_state_;
std::size_t total_chunks_;
private:
std::condition_variable chunk_notify_;
mutable std::mutex chunk_mtx_;
std::mutex read_mtx_;
std::unique_ptr<std::thread> reader_thread_;
std::size_t ring_begin_{};
std::size_t ring_end_{};
std::size_t ring_pos_{};
stop_type stop_requested_{false};
private:
[[nodiscard]] auto check_start() -> api_error;
auto download_chunk(std::size_t chunk, bool skip_active) -> api_error;
void reader_thread();
void update_position(std::size_t count, bool is_forward);
protected:
[[nodiscard]] auto has_reader_thread() const -> bool {
return reader_thread_ != nullptr;
}
[[nodiscard]] auto get_ring_size() const -> std::size_t {
return read_state_.size();
}
[[nodiscard]] virtual auto on_check_start() -> bool = 0;
[[nodiscard]] virtual auto
on_chunk_downloaded(std::size_t chunk,
const data_buffer &buffer) -> api_error = 0;
[[nodiscard]] virtual auto
on_read_chunk(std::size_t chunk, std::size_t read_size,
std::uint64_t read_offset, data_buffer &data,
std::size_t &bytes_read) -> api_error = 0;
[[nodiscard]] virtual auto
use_buffer(std::size_t chunk,
std::function<api_error(data_buffer &)> func) -> api_error = 0;
public:
auto close() -> bool override;
void forward(std::size_t count);
[[nodiscard]] auto get_current_chunk() const -> std::size_t {
return ring_pos_;
}
[[nodiscard]] auto get_first_chunk() const -> std::size_t {
return ring_begin_;
}
[[nodiscard]] auto get_last_chunk() const -> std::size_t { return ring_end_; }
[[nodiscard]] auto get_read_state() const -> boost::dynamic_bitset<> override;
[[nodiscard]] auto get_read_state(std::size_t chunk) const -> bool override;
[[nodiscard]] auto get_total_chunks() const -> std::size_t {
return total_chunks_;
}
[[nodiscard]] auto is_complete() const -> bool override { return false; }
[[nodiscard]] auto is_write_supported() const -> bool override {
return false;
}
[[nodiscard]] auto read(std::size_t read_size, std::uint64_t read_offset,
data_buffer &data) -> api_error override;
[[nodiscard]] auto resize(std::uint64_t /* size */) -> api_error override {
return api_error::not_supported;
}
void reverse(std::size_t count);
void set(std::size_t first_chunk, std::size_t current_chunk);
void set_api_path(const std::string &api_path) override;
[[nodiscard]] auto
write(std::uint64_t /* write_offset */, const data_buffer & /* data */,
std::size_t & /* bytes_written */) -> api_error override {
return api_error::not_supported;
}
};
} // namespace repertory
#endif // REPERTORY_INCLUDE_FILE_MANAGER_RING_BUFFER_BASE_HPP_

View File

@ -0,0 +1,93 @@
/*
Copyright <2018-2024> <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 REPERTORY_INCLUDE_FILE_MANAGER_RING_BUFFER_OPEN_FILE_HPP_
#define REPERTORY_INCLUDE_FILE_MANAGER_RING_BUFFER_OPEN_FILE_HPP_
#include "file_manager/ring_buffer_base.hpp"
#include "types/repertory.hpp"
#include "utils/file.hpp"
namespace repertory {
class i_provider;
class i_upload_manager;
class ring_buffer_open_file final : public ring_buffer_base {
public:
ring_buffer_open_file(std::string buffer_directory, std::uint64_t chunk_size,
std::uint8_t chunk_timeout, filesystem_item fsi,
i_provider &provider, std::size_t ring_size);
~ring_buffer_open_file() override;
public:
ring_buffer_open_file() = delete;
ring_buffer_open_file(const ring_buffer_open_file &) noexcept = delete;
ring_buffer_open_file(ring_buffer_open_file &&) noexcept = delete;
auto operator=(ring_buffer_open_file &&) noexcept -> ring_buffer_open_file & =
delete;
auto operator=(const ring_buffer_open_file &) noexcept
-> ring_buffer_open_file & = delete;
private:
std::string source_path_;
private:
std::unique_ptr<utils::file::i_file> nf_;
protected:
[[nodiscard]] auto on_check_start() -> bool override;
[[nodiscard]] auto
on_chunk_downloaded(std::size_t chunk,
const data_buffer &buffer) -> api_error override;
[[nodiscard]] auto
on_read_chunk(std::size_t chunk, std::size_t read_size,
std::uint64_t read_offset, data_buffer &data,
std::size_t &bytes_read) -> api_error override;
[[nodiscard]] auto use_buffer(std::size_t chunk,
std::function<api_error(data_buffer &)> func)
-> api_error override;
public:
[[nodiscard]] static auto can_handle_file(std::uint64_t file_size,
std::size_t chunk_size,
std::size_t ring_size) -> bool;
[[nodiscard]] auto
native_operation(native_operation_callback callback) -> api_error override;
[[nodiscard]] auto native_operation(std::uint64_t /* new_file_size */,
native_operation_callback /* callback */)
-> api_error override {
return api_error::not_supported;
}
[[nodiscard]] auto get_source_path() const -> std::string override {
return source_path_;
}
};
} // namespace repertory
#endif // REPERTORY_INCLUDE_FILE_MANAGER_RING_BUFFER_OPEN_FILE_HPP_

View File

@ -0,0 +1,75 @@
/*
Copyright <2018-2024> <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 REPERTORY_INCLUDE_FILE_MANAGER_UPLOAD_HPP_
#define REPERTORY_INCLUDE_FILE_MANAGER_UPLOAD_HPP_
#include "types/repertory.hpp"
namespace repertory {
class i_provider;
class upload final {
public:
upload(filesystem_item fsi, i_provider &provider);
~upload();
public:
upload() = delete;
upload(const upload &) noexcept = delete;
upload(upload &&) noexcept = delete;
auto operator=(upload &&) noexcept -> upload & = delete;
auto operator=(const upload &) noexcept -> upload & = delete;
private:
filesystem_item fsi_;
i_provider &provider_;
private:
bool cancelled_{false};
api_error error_{api_error::success};
std::unique_ptr<std::thread> thread_;
stop_type stop_requested_{false};
private:
void upload_thread();
public:
void cancel();
[[nodiscard]] auto get_api_error() const -> api_error { return error_; }
[[nodiscard]] auto get_api_path() const -> std::string {
return fsi_.api_path;
}
[[nodiscard]] auto get_source_path() const -> std::string {
return fsi_.source_path;
}
[[nodiscard]] auto is_cancelled() const -> bool { return cancelled_; }
void stop();
};
} // namespace repertory
#endif // REPERTORY_INCLUDE_FILE_MANAGER_UPLOAD_HPP_

View File

@ -22,11 +22,14 @@
#ifndef REPERTORY_INCLUDE_PLATFORM_PLATFORM_HPP_ #ifndef REPERTORY_INCLUDE_PLATFORM_PLATFORM_HPP_
#define REPERTORY_INCLUDE_PLATFORM_PLATFORM_HPP_ #define REPERTORY_INCLUDE_PLATFORM_PLATFORM_HPP_
#include "platform/unix_platform.hpp" #if defined(_WIN32)
#include "platform/win32_platform.hpp" #include "platform/win32_platform.hpp"
#include "utils/unix.hpp"
#include "utils/unix/unix_utils.hpp"
#include "utils/windows.hpp" #include "utils/windows.hpp"
#include "utils/windows/windows_utils.hpp" #include "utils/windows/windows_utils.hpp"
#else // !defined(_WIN32)
#include "platform/unix_platform.hpp"
#include "utils/unix.hpp"
#include "utils/unix/unix_utils.hpp"
#endif // defined(_WIN32)
#endif // REPERTORY_INCLUDE_PLATFORM_PLATFORM_HPP_ #endif // REPERTORY_INCLUDE_PLATFORM_PLATFORM_HPP_

View File

@ -22,8 +22,8 @@
#ifndef REPERTORY_INCLUDE_PROVIDERS_BASE_PROVIDER_HPP_ #ifndef REPERTORY_INCLUDE_PROVIDERS_BASE_PROVIDER_HPP_
#define REPERTORY_INCLUDE_PROVIDERS_BASE_PROVIDER_HPP_ #define REPERTORY_INCLUDE_PROVIDERS_BASE_PROVIDER_HPP_
#include "db/i_meta_db.hpp"
#include "providers/i_provider.hpp" #include "providers/i_provider.hpp"
#include "providers/meta_db.hpp"
#include "types/repertory.hpp" #include "types/repertory.hpp"
namespace repertory { namespace repertory {
@ -32,6 +32,13 @@ class i_file_manager;
class i_http_comm; class i_http_comm;
class base_provider : public i_provider { class base_provider : public i_provider {
private:
struct removed_item final {
std::string api_path;
bool directory{};
std::string source_path;
};
public: public:
base_provider(app_config &config, i_http_comm &comm) base_provider(app_config &config, i_http_comm &comm)
: config_(config), comm_(comm) {} : config_(config), comm_(comm) {}
@ -42,24 +49,37 @@ private:
private: private:
api_item_added_callback api_item_added_; api_item_added_callback api_item_added_;
std::unique_ptr<meta_db> db3_; std::unique_ptr<i_meta_db> db3_;
i_file_manager *fm_{}; i_file_manager *fm_{};
private: private:
void remove_deleted_files(bool source_only); void add_all_items(const stop_type &stop_requested);
void process_removed_directories(std::deque<removed_item> removed_list,
const stop_type &stop_requested);
void process_removed_files(std::deque<removed_item> removed_list,
const stop_type &stop_requested);
void process_removed_items(const stop_type &stop_requested);
void remove_deleted_items(const stop_type &stop_requested);
void remove_unmatched_source_files(const stop_type &stop_requested);
protected: protected:
[[nodiscard]] static auto [[nodiscard]] static auto create_api_file(std::string path, std::string key,
create_api_file(std::string path, std::string key, std::uint64_t size, std::uint64_t size,
std::uint64_t file_time) -> api_file; std::uint64_t file_time)
-> api_file;
[[nodiscard]] static auto create_api_file(std::string path, [[nodiscard]] static auto create_api_file(std::string path,
std::uint64_t size, std::uint64_t size,
api_meta_map &meta) -> api_file; api_meta_map &meta) -> api_file;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto create_directory_impl(const std::string &api_path,
create_directory_impl(const std::string &api_path, api_meta_map &meta)
api_meta_map &meta) -> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
create_file_extra(const std::string & /* api_path */, create_file_extra(const std::string & /* api_path */,
@ -71,12 +91,14 @@ protected:
return api_item_added_; return api_item_added_;
} }
[[nodiscard]] auto [[nodiscard]] auto get_api_item_added() const
get_api_item_added() const -> const api_item_added_callback & { -> const api_item_added_callback & {
return api_item_added_; return api_item_added_;
} }
[[nodiscard]] auto get_comm() const -> i_http_comm & { return comm_; } [[nodiscard]] auto get_comm() -> i_http_comm & { return comm_; }
[[nodiscard]] auto get_comm() const -> const i_http_comm & { return comm_; }
[[nodiscard]] auto get_config() -> app_config & { return config_; } [[nodiscard]] auto get_config() -> app_config & { return config_; }
@ -84,7 +106,9 @@ protected:
return config_; return config_;
} }
[[nodiscard]] auto get_db() -> meta_db & { return *db3_; } [[nodiscard]] auto get_db() -> i_meta_db & { return *db3_; }
[[nodiscard]] auto get_db() const -> const i_meta_db & { return *db3_; }
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
get_directory_items_impl(const std::string &api_path, get_directory_items_impl(const std::string &api_path,
@ -96,23 +120,22 @@ protected:
return fm_; return fm_;
} }
[[nodiscard]] virtual auto [[nodiscard]] virtual auto remove_directory_impl(const std::string &api_path)
get_used_drive_space_impl() const -> std::uint64_t = 0; -> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto remove_file_impl(const std::string &api_path)
remove_directory_impl(const std::string &api_path) -> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto upload_file_impl(const std::string &api_path,
remove_file_impl(const std::string &api_path) -> api_error = 0; const std::string &source_path,
stop_type &stop_requested)
[[nodiscard]] virtual auto -> api_error = 0;
upload_file_impl(const std::string &api_path, const std::string &source_path,
stop_type &stop_requested) -> api_error = 0;
public: public:
[[nodiscard]] auto create_directory_clone_source_meta( [[nodiscard]] auto
const std::string &source_api_path, create_directory_clone_source_meta(const std::string &source_api_path,
const std::string &api_path) -> api_error override; const std::string &api_path)
-> api_error override;
[[nodiscard]] auto create_directory(const std::string &api_path, [[nodiscard]] auto create_directory(const std::string &api_path,
api_meta_map &meta) -> api_error override; api_meta_map &meta) -> api_error override;
@ -120,74 +143,82 @@ public:
[[nodiscard]] auto create_file(const std::string &api_path, [[nodiscard]] auto create_file(const std::string &api_path,
api_meta_map &meta) -> api_error override; api_meta_map &meta) -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto get_api_path_from_source(const std::string &source_path,
get_api_path_from_source(const std::string &source_path, std::string &api_path) const
std::string &api_path) const -> api_error override; -> api_error override;
[[nodiscard]] auto get_directory_items(const std::string &api_path,
directory_item_list &list) const
-> api_error override;
[[nodiscard]] auto get_file_size(const std::string &api_path,
std::uint64_t &file_size) const
-> api_error override;
[[nodiscard]] auto get_filesystem_item(const std::string &api_path,
bool directory,
filesystem_item &fsi) const
-> api_error override;
[[nodiscard]] auto get_filesystem_item_and_file(const std::string &api_path,
api_file &f,
filesystem_item &fsi) const
-> api_error override;
[[nodiscard]] auto [[nodiscard]] auto
get_directory_items(const std::string &api_path, get_filesystem_item_from_source_path(const std::string &source_path,
directory_item_list &list) const -> api_error override; filesystem_item &fsi) const
-> api_error override;
[[nodiscard]] auto [[nodiscard]] auto get_item_meta(const std::string &api_path,
get_file_size(const std::string &api_path, api_meta_map &meta) const
std::uint64_t &file_size) const -> api_error override; -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto get_item_meta(const std::string &api_path,
get_filesystem_item(const std::string &api_path, bool directory, const std::string &key,
filesystem_item &fsi) const -> api_error override; std::string &value) const
-> api_error override;
[[nodiscard]] auto get_filesystem_item_and_file( [[nodiscard]] auto get_pinned_files() const
const std::string &api_path, api_file &f, -> std::vector<std::string> override;
filesystem_item &fsi) const -> api_error override;
[[nodiscard]] auto get_filesystem_item_from_source_path(
const std::string &source_path,
filesystem_item &fsi) const -> api_error override;
[[nodiscard]] auto
get_item_meta(const std::string &api_path,
api_meta_map &meta) const -> api_error override;
[[nodiscard]] auto
get_item_meta(const std::string &api_path, const std::string &key,
std::string &value) const -> api_error override;
[[nodiscard]] auto
get_pinned_files() const -> std::vector<std::string> override;
[[nodiscard]] auto get_total_item_count() const -> std::uint64_t override; [[nodiscard]] auto get_total_item_count() const -> std::uint64_t override;
[[nodiscard]] auto get_used_drive_space() const -> std::uint64_t override; [[nodiscard]] auto get_used_drive_space() const -> std::uint64_t override;
[[nodiscard]] auto [[nodiscard]] auto is_file_writeable(const std::string &api_path) const
is_file_writeable(const std::string &api_path) const -> bool override; -> bool override;
[[nodiscard]] auto [[nodiscard]] auto is_read_only() const -> bool override { return false; }
remove_directory(const std::string &api_path) -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto remove_directory(const std::string &api_path)
remove_file(const std::string &api_path) -> api_error override; -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto remove_file(const std::string &api_path)
remove_item_meta(const std::string &api_path, -> api_error override;
const std::string &key) -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto remove_item_meta(const std::string &api_path,
set_item_meta(const std::string &api_path, const std::string &key, const std::string &key)
const std::string &value) -> api_error override; -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto set_item_meta(const std::string &api_path,
set_item_meta(const std::string &api_path, const std::string &key,
const api_meta_map &meta) -> api_error override; const std::string &value)
-> api_error override;
[[nodiscard]] auto set_item_meta(const std::string &api_path,
const api_meta_map &meta)
-> api_error override;
[[nodiscard]] auto start(api_item_added_callback api_item_added, [[nodiscard]] auto start(api_item_added_callback api_item_added,
i_file_manager *mgr) -> bool override; i_file_manager *mgr) -> bool override;
void stop() override; void stop() override;
[[nodiscard]] auto [[nodiscard]] auto upload_file(const std::string &api_path,
upload_file(const std::string &api_path, const std::string &source_path, const std::string &source_path,
stop_type &stop_requested) -> api_error override; stop_type &stop_requested)
-> api_error override;
}; };
} // namespace repertory } // namespace repertory

View File

@ -23,8 +23,8 @@
#define REPERTORY_INCLUDE_PROVIDERS_ENCRYPT_ENCRYPT_PROVIDER_HPP_ #define REPERTORY_INCLUDE_PROVIDERS_ENCRYPT_ENCRYPT_PROVIDER_HPP_
#include "app_config.hpp" #include "app_config.hpp"
#include "db/i_file_db.hpp"
#include "providers/i_provider.hpp" #include "providers/i_provider.hpp"
#include "utils/db/sqlite/db_common.hpp"
#include "utils/encrypting_reader.hpp" #include "utils/encrypting_reader.hpp"
namespace repertory { namespace repertory {
@ -45,21 +45,22 @@ public:
private: private:
struct reader_info final { struct reader_info final {
std::chrono::system_clock::time_point last_access_time = std::chrono::system_clock::time_point last_access_time{
std::chrono::system_clock::now(); std::chrono::system_clock::now(),
std::unique_ptr<utils::encryption::encrypting_reader> reader{}; };
std::unique_ptr<utils::encryption::encrypting_reader> reader;
std::mutex reader_mtx; std::mutex reader_mtx;
}; };
private: private:
app_config &config_; app_config &config_;
utils::db::sqlite::db3_t db_; encrypt_config encrypt_config_;
private: private:
i_file_manager *fm_ = nullptr; std::unique_ptr<i_file_db> db_{nullptr};
std::unordered_map<std::string, std::shared_ptr<reader_info>> i_file_manager *fm_{nullptr};
reader_lookup_{}; std::unordered_map<std::string, std::shared_ptr<reader_info>> reader_lookup_;
std::recursive_mutex reader_lookup_mtx_{}; std::recursive_mutex reader_lookup_mtx_;
private: private:
static auto create_api_file(const std::string &api_path, bool directory, static auto create_api_file(const std::string &api_path, bool directory,
@ -73,71 +74,82 @@ private:
const std::string &source_path)> const std::string &source_path)>
callback) const -> api_error; callback) const -> api_error;
[[nodiscard]] auto get_encrypt_config() const -> const encrypt_config & {
return encrypt_config_;
}
auto process_directory_entry(const utils::file::i_fs_item &dir_entry, auto process_directory_entry(const utils::file::i_fs_item &dir_entry,
const encrypt_config &cfg, const encrypt_config &cfg,
std::string &api_path) const -> bool; std::string &api_path) const -> bool;
void remove_deleted_files(); void remove_deleted_files(const stop_type &stop_requested);
public: public:
[[nodiscard]] auto create_directory(const std::string &api_path, [[nodiscard]] auto create_directory(const std::string &api_path,
api_meta_map &meta) -> api_error override; api_meta_map &meta) -> api_error override;
[[nodiscard]] auto create_directory_clone_source_meta( [[nodiscard]] auto
const std::string & /*source_api_path*/, create_directory_clone_source_meta(const std::string & /*source_api_path*/,
const std::string & /*api_path*/) -> api_error override { const std::string & /*api_path*/)
-> api_error override {
return api_error::not_implemented;
}
[[nodiscard]] auto create_file(const std::string & /*api_path*/,
api_meta_map & /*meta*/)
-> api_error override {
return api_error::not_implemented; return api_error::not_implemented;
} }
[[nodiscard]] auto [[nodiscard]] auto
create_file(const std::string & /*api_path*/, get_api_path_from_source(const std::string & /*source_path*/,
api_meta_map & /*meta*/) -> api_error override { std::string & /*api_path*/) const
return api_error::not_implemented; -> api_error override;
}
[[nodiscard]] auto get_api_path_from_source(
const std::string & /*source_path*/,
std::string & /*api_path*/) const -> api_error 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;
[[nodiscard]] auto [[nodiscard]] auto get_directory_items(const std::string &api_path,
get_directory_items(const std::string &api_path, directory_item_list &list) const
directory_item_list &list) const -> api_error override; -> api_error override;
[[nodiscard]] auto get_file(const std::string &api_path, [[nodiscard]] auto get_file(const std::string &api_path, api_file &file) const
api_file &file) const -> api_error override; -> api_error override;
[[nodiscard]] auto get_file_list(api_file_list &list,
std::string &marker) const
-> api_error override;
[[nodiscard]] auto get_file_size(const std::string &api_path,
std::uint64_t &file_size) const
-> api_error override;
[[nodiscard]] auto get_filesystem_item(const std::string &api_path,
bool directory,
filesystem_item &fsi) const
-> api_error override;
[[nodiscard]] auto get_filesystem_item_and_file(const std::string &api_path,
api_file &file,
filesystem_item &fsi) const
-> api_error override;
[[nodiscard]] auto [[nodiscard]] auto
get_file_list(api_file_list &list) const -> api_error override; get_filesystem_item_from_source_path(const std::string &source_path,
filesystem_item &fsi) const
-> api_error override;
[[nodiscard]] auto [[nodiscard]] auto get_pinned_files() const
get_file_size(const std::string &api_path, -> std::vector<std::string> override;
std::uint64_t &file_size) const -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto get_item_meta(const std::string &api_path,
get_filesystem_item(const std::string &api_path, bool directory, api_meta_map &meta) const
filesystem_item &fsi) const -> api_error override; -> api_error override;
[[nodiscard]] auto get_filesystem_item_and_file( [[nodiscard]] auto get_item_meta(const std::string &api_path,
const std::string &api_path, api_file &file, const std::string &key,
filesystem_item &fsi) const -> api_error override; std::string &value) const
-> api_error override;
[[nodiscard]] auto get_filesystem_item_from_source_path(
const std::string &source_path,
filesystem_item &fsi) const -> api_error override;
[[nodiscard]] auto
get_pinned_files() const -> std::vector<std::string> override;
[[nodiscard]] auto
get_item_meta(const std::string &api_path,
api_meta_map &meta) const -> api_error override;
[[nodiscard]] auto
get_item_meta(const std::string &api_path, const std::string &key,
std::string &value) const -> api_error override;
[[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override; [[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override;
@ -149,57 +161,61 @@ public:
[[nodiscard]] auto get_used_drive_space() const -> std::uint64_t override; [[nodiscard]] auto get_used_drive_space() const -> std::uint64_t override;
[[nodiscard]] auto is_direct_only() const -> bool override { return true; }
[[nodiscard]] auto is_directory(const std::string &api_path, [[nodiscard]] auto is_directory(const std::string &api_path,
bool &exists) const -> api_error override; bool &exists) const -> api_error override;
[[nodiscard]] auto is_file(const std::string &api_path, [[nodiscard]] auto is_file(const std::string &api_path, bool &exists) const
bool &exists) const -> api_error override; -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto is_file_writeable(const std::string &api_path) const
is_file_writeable(const std::string &api_path) const -> bool override; -> bool override;
[[nodiscard]] auto is_online() const -> bool override; [[nodiscard]] auto is_online() const -> bool override;
[[nodiscard]] auto is_rename_supported() const -> bool override; [[nodiscard]] auto is_read_only() const -> bool override { return true; }
[[nodiscard]] auto [[nodiscard]] auto is_rename_supported() const -> bool override {
read_file_bytes(const std::string &api_path, std::size_t size, return false;
std::uint64_t offset, data_buffer &data, }
stop_type &stop_requested) -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto read_file_bytes(const std::string &api_path,
remove_directory(const std::string & /*api_path*/) -> api_error override { std::size_t size, std::uint64_t offset,
data_buffer &data,
stop_type &stop_requested)
-> api_error override;
[[nodiscard]] auto remove_directory(const std::string & /*api_path*/)
-> api_error override {
return api_error::not_implemented; return api_error::not_implemented;
} }
[[nodiscard]] auto [[nodiscard]] auto remove_file(const std::string & /*api_path*/)
remove_file(const std::string & /*api_path*/) -> api_error override { -> api_error override {
return api_error::not_implemented; return api_error::not_implemented;
} }
[[nodiscard]] auto [[nodiscard]] auto remove_item_meta(const std::string & /*api_path*/,
remove_item_meta(const std::string & /*api_path*/, const std::string & /*key*/)
const std::string & /*key*/) -> api_error override { -> api_error override {
return api_error::success; return api_error::success;
} }
[[nodiscard]] auto [[nodiscard]] auto rename_file(const std::string & /*from_api_path*/,
rename_file(const std::string & /*from_api_path*/, const std::string & /*to_api_path*/)
const std::string & /*to_api_path*/) -> api_error override { -> api_error override {
return api_error::not_implemented; return api_error::not_implemented;
} }
[[nodiscard]] auto [[nodiscard]] auto set_item_meta(const std::string & /*api_path*/,
set_item_meta(const std::string & /*api_path*/, const std::string & /*key*/, const std::string & /*key*/,
const std::string & /*value*/) -> api_error override { const std::string & /*value*/)
-> api_error override {
return api_error::success; return api_error::success;
} }
[[nodiscard]] auto [[nodiscard]] auto set_item_meta(const std::string & /*api_path*/,
set_item_meta(const std::string & /*api_path*/, const api_meta_map & /*meta*/)
const api_meta_map & /*meta*/) -> api_error override { -> api_error override {
return api_error::success; return api_error::success;
} }
@ -208,10 +224,10 @@ public:
void stop() override; void stop() override;
[[nodiscard]] auto [[nodiscard]] auto upload_file(const std::string & /*api_path*/,
upload_file(const std::string & /*api_path*/, const std::string & /*source_path*/,
const std::string & /*source_path*/, stop_type & /*stop_requested*/)
stop_type & /*stop_requested*/) -> api_error override { -> api_error override {
return api_error::not_implemented; return api_error::not_implemented;
} }
}; };

View File

@ -31,13 +31,14 @@ class i_provider {
INTERFACE_SETUP(i_provider); INTERFACE_SETUP(i_provider);
public: public:
[[nodiscard]] virtual auto [[nodiscard]] virtual auto create_directory(const std::string &api_path,
create_directory(const std::string &api_path, api_meta_map &meta)
api_meta_map &meta) -> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto create_directory_clone_source_meta( [[nodiscard]] virtual auto
const std::string &source_api_path, create_directory_clone_source_meta(const std::string &source_api_path,
const std::string &api_path) -> api_error = 0; const std::string &api_path)
-> api_error = 0;
[[nodiscard]] virtual auto create_file(const std::string &api_path, [[nodiscard]] virtual auto create_file(const std::string &api_path,
api_meta_map &meta) -> api_error = 0; api_meta_map &meta) -> api_error = 0;
@ -46,8 +47,9 @@ public:
get_api_path_from_source(const std::string &source_path, get_api_path_from_source(const std::string &source_path,
std::string &api_path) const -> api_error = 0; std::string &api_path) const -> api_error = 0;
[[nodiscard]] virtual auto get_directory_item_count( [[nodiscard]] virtual auto
const std::string &api_path) const -> std::uint64_t = 0; get_directory_item_count(const std::string &api_path) const
-> std::uint64_t = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
get_directory_items(const std::string &api_path, get_directory_items(const std::string &api_path,
@ -56,35 +58,39 @@ public:
[[nodiscard]] virtual auto get_file(const std::string &api_path, [[nodiscard]] virtual auto get_file(const std::string &api_path,
api_file &file) const -> api_error = 0; api_file &file) const -> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto get_file_list(api_file_list &list,
get_file_list(api_file_list &list) const -> api_error = 0; std::string &marker) const
-> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto get_file_size(const std::string &api_path,
get_file_size(const std::string &api_path, std::uint64_t &file_size) const
std::uint64_t &file_size) const -> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto get_filesystem_item(const std::string &api_path,
get_filesystem_item(const std::string &api_path, bool directory, bool directory,
filesystem_item &fsi) const -> api_error = 0; filesystem_item &fsi) const
-> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
get_filesystem_item_and_file(const std::string &api_path, api_file &file, get_filesystem_item_and_file(const std::string &api_path, api_file &file,
filesystem_item &fsi) const -> api_error = 0; filesystem_item &fsi) const -> api_error = 0;
[[nodiscard]] virtual auto get_filesystem_item_from_source_path(
const std::string &source_path,
filesystem_item &fsi) const -> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
get_item_meta(const std::string &api_path, get_filesystem_item_from_source_path(const std::string &source_path,
api_meta_map &meta) const -> api_error = 0; filesystem_item &fsi) const
-> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto get_item_meta(const std::string &api_path,
get_item_meta(const std::string &api_path, const std::string &key, api_meta_map &meta) const
std::string &value) const -> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto get_item_meta(const std::string &api_path,
get_pinned_files() const -> std::vector<std::string> = 0; const std::string &key,
std::string &value) const
-> api_error = 0;
[[nodiscard]] virtual auto get_pinned_files() const
-> std::vector<std::string> = 0;
[[nodiscard]] virtual auto get_provider_type() const -> provider_type = 0; [[nodiscard]] virtual auto get_provider_type() const -> provider_type = 0;
@ -94,8 +100,6 @@ public:
[[nodiscard]] virtual auto get_used_drive_space() const -> std::uint64_t = 0; [[nodiscard]] virtual auto get_used_drive_space() const -> std::uint64_t = 0;
[[nodiscard]] virtual auto is_direct_only() const -> bool = 0;
[[nodiscard]] virtual auto is_directory(const std::string &api_path, [[nodiscard]] virtual auto is_directory(const std::string &api_path,
bool &exists) const -> api_error = 0; bool &exists) const -> api_error = 0;
@ -107,6 +111,8 @@ public:
[[nodiscard]] virtual auto is_online() const -> bool = 0; [[nodiscard]] virtual auto is_online() const -> bool = 0;
[[nodiscard]] virtual auto is_read_only() const -> bool = 0;
[[nodiscard]] virtual auto is_rename_supported() const -> bool = 0; [[nodiscard]] virtual auto is_rename_supported() const -> bool = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
@ -114,36 +120,38 @@ public:
std::uint64_t offset, data_buffer &data, std::uint64_t offset, data_buffer &data,
stop_type &stop_requested) -> api_error = 0; stop_type &stop_requested) -> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto remove_directory(const std::string &api_path)
remove_directory(const std::string &api_path) -> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto remove_file(const std::string &api_path)
remove_file(const std::string &api_path) -> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto remove_item_meta(const std::string &api_path,
remove_item_meta(const std::string &api_path, const std::string &key)
const std::string &key) -> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto rename_file(const std::string &from_api_path,
rename_file(const std::string &from_api_path, const std::string &to_api_path)
const std::string &to_api_path) -> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto set_item_meta(const std::string &api_path,
set_item_meta(const std::string &api_path, const std::string &key, const std::string &key,
const std::string &value) -> api_error = 0; const std::string &value)
-> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto set_item_meta(const std::string &api_path,
set_item_meta(const std::string &api_path, const api_meta_map &meta)
const api_meta_map &meta) -> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto start(api_item_added_callback api_item_added, [[nodiscard]] virtual auto start(api_item_added_callback api_item_added,
i_file_manager *mgr) -> bool = 0; i_file_manager *mgr) -> bool = 0;
virtual void stop() = 0; virtual void stop() = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto upload_file(const std::string &api_path,
upload_file(const std::string &api_path, const std::string &source_path, const std::string &source_path,
stop_type &stop_requested) -> api_error = 0; stop_type &stop_requested)
-> api_error = 0;
}; };
} // namespace repertory } // namespace repertory

View File

@ -47,69 +47,77 @@ public:
auto operator=(s3_provider &&) -> s3_provider & = delete; auto operator=(s3_provider &&) -> s3_provider & = delete;
private: private:
[[nodiscard]] auto s3_config s3_config_;
add_if_not_found(api_file &file,
const std::string &object_name) const -> api_error;
[[nodiscard]] auto private:
create_file_extra(const std::string &api_path, [[nodiscard]] auto add_if_not_found(api_file &file,
api_meta_map &meta) -> api_error override; const std::string &object_name) const
-> api_error;
[[nodiscard]] auto [[nodiscard]] auto create_file_extra(const std::string &api_path,
create_path_directories(const std::string &api_path, api_meta_map &meta)
const std::string &key) const -> api_error; -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto create_path_directories(const std::string &api_path,
decrypt_object_name(std::string &object_name) const -> api_error; const std::string &key) const
-> api_error;
[[nodiscard]] auto [[nodiscard]] auto decrypt_object_name(std::string &object_name) const
get_last_modified(bool directory, -> api_error;
const std::string &api_path) const -> std::uint64_t;
[[nodiscard]] auto get_last_modified(bool directory,
const std::string &api_path) const
-> std::uint64_t;
[[nodiscard]] auto [[nodiscard]] auto
get_object_info(bool directory, const std::string &api_path, get_object_info(bool directory, const std::string &api_path,
bool &is_encrypted, std::string &object_name, bool &is_encrypted, std::string &object_name,
head_object_result &result) const -> api_error; head_object_result &result) const -> api_error;
[[nodiscard]] auto get_object_list( [[nodiscard]] auto
std::string &response_data, long &response_code, get_object_list(std::string &response_data, long &response_code,
std::optional<std::string> delimiter = std::nullopt, std::optional<std::string> delimiter = std::nullopt,
std::optional<std::string> prefix = std::nullopt) const -> bool; std::optional<std::string> prefix = std::nullopt,
std::optional<std::string> token = std::nullopt) const
-> bool;
[[nodiscard]] auto get_s3_config() const -> const s3_config & {
return s3_config_;
}
protected: protected:
[[nodiscard]] auto [[nodiscard]] auto create_directory_impl(const std::string &api_path,
create_directory_impl(const std::string &api_path, api_meta_map &meta)
api_meta_map &meta) -> api_error override; -> api_error override;
[[nodiscard]] auto get_directory_items_impl(const std::string &api_path, [[nodiscard]] auto get_directory_items_impl(const std::string &api_path,
directory_item_list &list) const directory_item_list &list) const
-> api_error override; -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto remove_directory_impl(const std::string &api_path)
get_used_drive_space_impl() const -> std::uint64_t override; -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto remove_file_impl(const std::string &api_path)
remove_directory_impl(const std::string &api_path) -> api_error override; -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto upload_file_impl(const std::string &api_path,
remove_file_impl(const std::string &api_path) -> api_error override; const std::string &source_path,
stop_type &stop_requested)
[[nodiscard]] auto -> api_error override;
upload_file_impl(const std::string &api_path, const std::string &source_path,
stop_type &stop_requested) -> api_error override;
public: public:
[[nodiscard]] static auto [[nodiscard]] static auto convert_api_date(std::string_view date)
convert_api_date(std::string_view date) -> std::uint64_t; -> std::uint64_t;
[[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;
[[nodiscard]] auto get_file(const std::string &api_path, [[nodiscard]] auto get_file(const std::string &api_path, api_file &file) const
api_file &file) const -> api_error override; -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto get_file_list(api_file_list &list,
get_file_list(api_file_list &list) const -> api_error override; std::string &marker) const
-> api_error override;
[[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override; [[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override;
@ -117,13 +125,11 @@ public:
return type; return type;
} }
[[nodiscard]] auto is_direct_only() const -> bool override { return false; }
[[nodiscard]] auto is_directory(const std::string &api_path, [[nodiscard]] auto is_directory(const std::string &api_path,
bool &exists) const -> api_error override; bool &exists) const -> api_error override;
[[nodiscard]] auto is_file(const std::string &api_path, [[nodiscard]] auto is_file(const std::string &api_path, bool &exists) const
bool &exists) const -> api_error override; -> api_error override;
[[nodiscard]] auto is_online() const -> bool override; [[nodiscard]] auto is_online() const -> bool override;
@ -131,14 +137,15 @@ public:
return false; return false;
}; };
[[nodiscard]] auto [[nodiscard]] auto read_file_bytes(const std::string &api_path,
read_file_bytes(const std::string &api_path, std::size_t size, std::size_t size, std::uint64_t offset,
std::uint64_t offset, data_buffer &data, data_buffer &data,
stop_type &stop_requested) -> api_error override; stop_type &stop_requested)
-> api_error override;
[[nodiscard]] auto [[nodiscard]] auto rename_file(const std::string &from_api_path,
rename_file(const std::string &from_api_path, const std::string &to_api_path)
const std::string &to_api_path) -> api_error override; -> api_error override;
[[nodiscard]] auto start(api_item_added_callback api_item_added, [[nodiscard]] auto start(api_item_added_callback api_item_added,
i_file_manager *mgr) -> bool override; i_file_manager *mgr) -> bool override;

View File

@ -45,6 +45,9 @@ public:
auto operator=(const sia_provider &) -> sia_provider & = delete; auto operator=(const sia_provider &) -> sia_provider & = delete;
auto operator=(sia_provider &&) -> sia_provider & = delete; auto operator=(sia_provider &&) -> sia_provider & = delete;
private:
sia_config sia_config_;
private: private:
[[nodiscard]] auto get_object_info(const std::string &api_path, [[nodiscard]] auto get_object_info(const std::string &api_path,
json &object_info) const -> api_error; json &object_info) const -> api_error;
@ -52,37 +55,40 @@ private:
[[nodiscard]] auto get_object_list(const std::string &api_path, [[nodiscard]] auto get_object_list(const std::string &api_path,
nlohmann::json &object_list) const -> bool; nlohmann::json &object_list) const -> bool;
[[nodiscard]] auto get_sia_config() const -> const auto & {
return sia_config_;
}
protected: protected:
[[nodiscard]] auto [[nodiscard]] auto create_directory_impl(const std::string &api_path,
create_directory_impl(const std::string &api_path, api_meta_map &meta)
api_meta_map &meta) -> api_error override; -> api_error override;
[[nodiscard]] auto get_directory_items_impl(const std::string &api_path, [[nodiscard]] auto get_directory_items_impl(const std::string &api_path,
directory_item_list &list) const directory_item_list &list) const
-> api_error override; -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto remove_directory_impl(const std::string &api_path)
get_used_drive_space_impl() const -> std::uint64_t override; -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto remove_file_impl(const std::string &api_path)
remove_directory_impl(const std::string &api_path) -> api_error override; -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto upload_file_impl(const std::string &api_path,
remove_file_impl(const std::string &api_path) -> api_error override; const std::string &source_path,
stop_type &stop_requested)
[[nodiscard]] auto -> api_error override;
upload_file_impl(const std::string &api_path, const std::string &source_path,
stop_type &stop_requested) -> api_error override;
public: public:
[[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;
[[nodiscard]] auto get_file(const std::string &api_path, [[nodiscard]] auto get_file(const std::string &api_path, api_file &file) const
api_file &file) const -> api_error override; -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto get_file_list(api_file_list &list,
get_file_list(api_file_list &list) const -> api_error override; std::string &marker) const
-> api_error override;
[[nodiscard]] auto get_provider_type() const -> provider_type override { [[nodiscard]] auto get_provider_type() const -> provider_type override {
return type; return type;
@ -90,13 +96,11 @@ public:
[[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override; [[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override;
[[nodiscard]] auto is_direct_only() const -> bool override { return false; }
[[nodiscard]] auto is_directory(const std::string &api_path, [[nodiscard]] auto is_directory(const std::string &api_path,
bool &exists) const -> api_error override; bool &exists) const -> api_error override;
[[nodiscard]] auto is_file(const std::string &api_path, [[nodiscard]] auto is_file(const std::string &api_path, bool &exists) const
bool &exists) const -> api_error override; -> api_error override;
[[nodiscard]] auto is_online() const -> bool override; [[nodiscard]] auto is_online() const -> bool override;
@ -104,14 +108,15 @@ public:
return true; return true;
} }
[[nodiscard]] auto [[nodiscard]] auto read_file_bytes(const std::string &api_path,
read_file_bytes(const std::string &api_path, std::size_t size, std::size_t size, std::uint64_t offset,
std::uint64_t offset, data_buffer &buffer, data_buffer &buffer,
stop_type &stop_requested) -> api_error override; stop_type &stop_requested)
-> api_error override;
[[nodiscard]] auto [[nodiscard]] auto rename_file(const std::string &from_api_path,
rename_file(const std::string &from_api_path, const std::string &to_api_path)
const std::string &to_api_path) -> api_error override; -> api_error override;
[[nodiscard]] auto start(api_item_added_callback api_item_added, [[nodiscard]] auto start(api_item_added_callback api_item_added,
i_file_manager *mgr) -> bool override; i_file_manager *mgr) -> bool override;

View File

@ -22,6 +22,8 @@
#ifndef REPERTORY_INCLUDE_TYPES_REMOTE_HPP_ #ifndef REPERTORY_INCLUDE_TYPES_REMOTE_HPP_
#define REPERTORY_INCLUDE_TYPES_REMOTE_HPP_ #define REPERTORY_INCLUDE_TYPES_REMOTE_HPP_
#include "types/repertory.hpp"
inline constexpr const auto PACKET_SERVICE_FUSE{1U}; inline constexpr const auto PACKET_SERVICE_FUSE{1U};
inline constexpr const auto PACKET_SERVICE_WINFSP{2U}; inline constexpr const auto PACKET_SERVICE_WINFSP{2U};
@ -31,7 +33,67 @@ inline constexpr const auto PACKET_SERVICE_FLAGS{PACKET_SERVICE_WINFSP};
inline constexpr const auto PACKET_SERVICE_FLAGS{PACKET_SERVICE_FUSE}; inline constexpr const auto PACKET_SERVICE_FLAGS{PACKET_SERVICE_FUSE};
#endif // defined(_WIN32) #endif // defined(_WIN32)
constexpr const auto default_remote_client_pool_size{20U};
constexpr const auto default_remote_max_connections{20U};
constexpr const auto default_remote_receive_timeout_ms{120U * 1000U};
constexpr const auto default_remote_send_timeout_ms{30U * 1000U};
namespace repertory::remote { namespace repertory::remote {
struct remote_config final {
std::uint16_t api_port{};
std::string encryption_token;
std::string host_name_or_ip;
std::uint8_t max_connections{default_remote_max_connections};
std::uint32_t recv_timeout_ms{default_remote_receive_timeout_ms};
std::uint32_t send_timeout_ms{default_remote_send_timeout_ms};
auto operator==(const remote_config &cfg) const noexcept -> bool {
if (&cfg != this) {
return api_port == cfg.api_port &&
encryption_token == cfg.encryption_token &&
host_name_or_ip == cfg.host_name_or_ip &&
max_connections == cfg.max_connections &&
recv_timeout_ms == cfg.recv_timeout_ms &&
send_timeout_ms == cfg.send_timeout_ms;
}
return true;
}
auto operator!=(const remote_config &cfg) const noexcept -> bool {
if (&cfg != this) {
return not(cfg == *this);
}
return false;
}
};
struct remote_mount final {
std::uint16_t api_port{};
std::uint8_t client_pool_size{default_remote_client_pool_size};
bool enable{false};
std::string encryption_token;
auto operator==(const remote_mount &cfg) const noexcept -> bool {
if (&cfg == this) {
return true;
}
return api_port == cfg.api_port &&
client_pool_size == cfg.client_pool_size && enable == cfg.enable &&
encryption_token == cfg.encryption_token;
}
auto operator!=(const remote_mount &cfg) const noexcept -> bool {
if (&cfg == this) {
return false;
}
return not(cfg == *this);
}
};
using block_count = std::uint64_t; using block_count = std::uint64_t;
using block_size = std::uint32_t; using block_size = std::uint32_t;
using file_handle = std::uint64_t; using file_handle = std::uint64_t;
@ -160,4 +222,46 @@ create_os_open_flags(const open_flags &flags) -> std::uint32_t;
#endif // !defined(_WIN32) #endif // !defined(_WIN32)
} // namespace repertory::remote } // namespace repertory::remote
NLOHMANN_JSON_NAMESPACE_BEGIN
template <> struct adl_serializer<repertory::remote::remote_config> {
static void to_json(json &data,
const repertory::remote::remote_config &value) {
data[repertory::JSON_API_PORT] = value.api_port;
data[repertory::JSON_ENCRYPTION_TOKEN] = value.encryption_token;
data[repertory::JSON_HOST_NAME_OR_IP] = value.host_name_or_ip;
data[repertory::JSON_MAX_CONNECTIONS] = value.max_connections;
data[repertory::JSON_RECV_TIMEOUT_MS] = value.recv_timeout_ms;
data[repertory::JSON_SEND_TIMEOUT_MS] = value.send_timeout_ms;
}
static void from_json(const json &data,
repertory::remote::remote_config &value) {
data.at(repertory::JSON_API_PORT).get_to(value.api_port);
data.at(repertory::JSON_ENCRYPTION_TOKEN).get_to(value.encryption_token);
data.at(repertory::JSON_HOST_NAME_OR_IP).get_to(value.host_name_or_ip);
data.at(repertory::JSON_MAX_CONNECTIONS).get_to(value.max_connections);
data.at(repertory::JSON_RECV_TIMEOUT_MS).get_to(value.recv_timeout_ms);
data.at(repertory::JSON_SEND_TIMEOUT_MS).get_to(value.send_timeout_ms);
}
};
template <> struct adl_serializer<repertory::remote::remote_mount> {
static void to_json(json &data,
const repertory::remote::remote_mount &value) {
data[repertory::JSON_API_PORT] = value.api_port;
data[repertory::JSON_CLIENT_POOL_SIZE] = value.client_pool_size;
data[repertory::JSON_ENABLE_REMOTE_MOUNT] = value.enable;
data[repertory::JSON_ENCRYPTION_TOKEN] = value.encryption_token;
}
static void from_json(const json &data,
repertory::remote::remote_mount &value) {
data.at(repertory::JSON_API_PORT).get_to(value.api_port);
data.at(repertory::JSON_CLIENT_POOL_SIZE).get_to(value.client_pool_size);
data.at(repertory::JSON_ENABLE_REMOTE_MOUNT).get_to(value.enable);
data.at(repertory::JSON_ENCRYPTION_TOKEN).get_to(value.encryption_token);
}
};
NLOHMANN_JSON_NAMESPACE_END
#endif // REPERTORY_INCLUDE_TYPES_REMOTE_HPP_ #endif // REPERTORY_INCLUDE_TYPES_REMOTE_HPP_

View File

@ -1,292 +1,655 @@
/* /*
Copyright <2018-2023> <scott.e.graves@protonmail.com> Copyright <2018-2023> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#ifndef REPERTORY_INCLUDE_TYPES_REPERTORY_HPP_ #ifndef REPERTORY_INCLUDE_TYPES_REPERTORY_HPP_
#define REPERTORY_INCLUDE_TYPES_REPERTORY_HPP_ #define REPERTORY_INCLUDE_TYPES_REPERTORY_HPP_
namespace repertory { namespace repertory {
inline constexpr const auto max_time{std::numeric_limits<std::uint64_t>::max()}; constexpr const auto default_api_auth_size{48U};
constexpr const auto default_download_timeout_ces{30U};
inline constexpr const std::string META_ACCESSED{"accessed"}; constexpr const auto default_eviction_delay_mins{1U};
inline constexpr const std::string META_ATTRIBUTES{"attributes"}; constexpr const auto default_high_freq_interval_secs{30U};
inline constexpr const std::string META_BACKUP{"backup"}; constexpr const auto default_low_freq_interval_secs{0U * 60U};
inline constexpr const std::string META_CHANGED{"changed"}; constexpr const auto default_max_cache_size_bytes{
inline constexpr const std::string META_CREATION{"creation"}; std::uint64_t(20UL * 1024UL * 1024UL * 1024UL),
inline constexpr const std::string META_DIRECTORY{"directory"}; };
inline constexpr const std::string META_GID{"gid"}; constexpr const auto default_max_upload_count{5U};
inline constexpr const std::string META_KEY{"key"}; constexpr const auto default_med_freq_interval_secs{2U * 60U};
inline constexpr const std::string META_MODE{"mode"}; constexpr const auto default_online_check_retry_secs{60U};
inline constexpr const std::string META_MODIFIED{"modified"}; constexpr const auto default_orphaned_file_retention_days{15U};
inline constexpr const std::string META_OSXFLAGS{"flags"}; constexpr const auto default_retry_read_count{6U};
inline constexpr const std::string META_PINNED{"pinned"}; constexpr const auto default_ring_buffer_file_size{512U};
inline constexpr const std::string META_SIZE{"size"}; constexpr const auto default_task_wait_ms{100U};
inline constexpr const std::string META_SOURCE{"source"}; constexpr const auto default_timeout_ms{60000U};
inline constexpr const std::string META_UID{"uid"}; constexpr const auto max_orphaned_file_retention_days{std::uint16_t(31U)};
inline constexpr const std::string META_WRITTEN{"written"}; constexpr const auto max_ring_buffer_file_size{std::uint16_t(1024U)};
constexpr const auto min_cache_size_bytes{
inline constexpr const std::array<std::string, 16U> META_USED_NAMES = { std::uint64_t(100UL * 1024UL * 1024UL)};
META_ACCESSED, META_ATTRIBUTES, META_BACKUP, META_CHANGED, constexpr const auto min_download_timeout_secs{std::uint8_t(5U)};
META_CREATION, META_DIRECTORY, META_GID, META_KEY, constexpr const auto min_online_check_retry_secs{std::uint16_t(15U)};
META_MODE, META_MODIFIED, META_OSXFLAGS, META_PINNED, constexpr const auto min_orphaned_file_retention_days{std::uint16_t(1U)};
META_SIZE, META_SOURCE, META_UID, META_WRITTEN, constexpr const auto min_retry_read_count{std::uint16_t(2U)};
}; constexpr const auto min_ring_buffer_file_size{std::uint16_t(64U)};
constexpr const auto min_task_wait_ms{std::uint16_t(50U)};
using api_meta_map = std::map<std::string, std::string>;
template <typename data_t> class atomic final {
enum class api_error { public:
success = 0, atomic() : mtx_(std::make_shared<std::mutex>()) {}
access_denied,
bad_address, atomic(const atomic &at_data)
buffer_overflow, : data_(at_data.load()), mtx_(std::make_shared<std::mutex>()) {}
buffer_too_small,
comm_error, atomic(data_t data)
decryption_error, : data_(std::move(data)), mtx_(std::make_shared<std::mutex>()) {}
directory_end_of_files,
directory_exists, atomic(atomic &&) = default;
directory_not_empty,
directory_not_found, ~atomic() = default;
download_failed,
download_incomplete, private:
download_stopped, data_t data_;
empty_ring_buffer_chunk_size, std::shared_ptr<std::mutex> mtx_;
empty_ring_buffer_size,
error, public:
file_in_use, [[nodiscard]] auto load() const -> data_t {
file_size_mismatch, mutex_lock lock(*mtx_);
incompatible_version, return data_;
invalid_handle, }
invalid_operation,
invalid_ring_buffer_multiple, auto store(data_t data) -> data_t {
invalid_ring_buffer_size, mutex_lock lock(*mtx_);
invalid_version, data_ = std::move(data);
item_exists, return data_;
item_not_found, }
no_disk_space,
not_implemented, auto operator=(const atomic &at_data) -> atomic & {
not_supported, if (&at_data == this) {
os_error, return *this;
out_of_memory, }
permission_denied,
upload_failed, store(at_data.load());
xattr_buffer_small, return *this;
xattr_exists, }
xattr_not_found,
xattr_too_big, auto operator=(atomic &&) -> atomic & = default;
ERROR_COUNT
}; auto operator=(data_t data) -> atomic & {
if (&data == &data_) {
[[nodiscard]] auto api_error_from_string(std::string_view str) -> api_error; return *this;
}
[[nodiscard]] auto
api_error_to_string(const api_error &error) -> const std::string &; store(std::move(data));
return *this;
enum class download_type { direct, fallback, ring_buffer }; }
[[nodiscard]] auto
download_type_from_string(std::string type, [[nodiscard]] auto operator==(const atomic &at_data) const -> bool {
const download_type &default_type) -> download_type; if (&at_data == this) {
return true;
[[nodiscard]] auto }
download_type_to_string(const download_type &type) -> std::string;
mutex_lock lock(*mtx_);
enum class exit_code : std::int32_t { return at_data.load() == data_;
success, }
communication_error = -1,
file_creation_failed = -2, [[nodiscard]] auto operator==(const data_t &data) const -> bool {
incompatible_version = -3, if (&data == &data_) {
invalid_syntax = -4, return true;
lock_failed = -5, }
mount_active = -6,
mount_result = -7, mutex_lock lock(*mtx_);
not_mounted = -8, return data == data_;
startup_exception = -9, }
failed_to_get_mount_state = -10,
export_failed = -11, [[nodiscard]] auto operator!=(const atomic &at_data) const -> bool {
import_failed = -12, if (&at_data == this) {
option_not_found = -13, return false;
invalid_provider_type = -14, }
set_option_not_found = -15,
pin_failed = -16, mutex_lock lock(*mtx_);
unpin_failed = -17, return at_data.load() != data_;
init_failed = -18, }
};
[[nodiscard]] auto operator!=(const data_t &data) const -> bool {
enum http_error_codes : std::int32_t { if (&data == &data_) {
ok = 200, return false;
multiple_choices = 300, }
not_found = 404,
}; mutex_lock lock(*mtx_);
return data != data_;
enum class lock_result { }
success,
locked, [[nodiscard]] operator data_t() const { return load(); }
failure, };
};
inline constexpr const auto max_time{
enum class provider_type : std::size_t { std::numeric_limits<std::uint64_t>::max(),
sia, };
remote,
s3, inline constexpr const std::string META_ACCESSED{"accessed"};
encrypt, inline constexpr const std::string META_ATTRIBUTES{"attributes"};
unknown, inline constexpr const std::string META_BACKUP{"backup"};
}; inline constexpr const std::string META_CHANGED{"changed"};
inline constexpr const std::string META_CREATION{"creation"};
#if defined(_WIN32) inline constexpr const std::string META_DIRECTORY{"directory"};
struct open_file_data final { inline constexpr const std::string META_GID{"gid"};
PVOID directory_buffer{nullptr}; inline constexpr const std::string META_KEY{"key"};
}; inline constexpr const std::string META_MODE{"mode"};
#else inline constexpr const std::string META_MODIFIED{"modified"};
using open_file_data = int; inline constexpr const std::string META_OSXFLAGS{"flags"};
#endif inline constexpr const std::string META_PINNED{"pinned"};
inline constexpr const std::string META_SIZE{"size"};
struct api_file final { inline constexpr const std::string META_SOURCE{"source"};
std::string api_path{}; inline constexpr const std::string META_UID{"uid"};
std::string api_parent{}; inline constexpr const std::string META_WRITTEN{"written"};
std::uint64_t accessed_date{};
std::uint64_t changed_date{}; inline constexpr const std::array<std::string, 16U> META_USED_NAMES = {
std::uint64_t creation_date{}; META_ACCESSED, META_ATTRIBUTES, META_BACKUP, META_CHANGED,
std::uint64_t file_size{}; META_CREATION, META_DIRECTORY, META_GID, META_KEY,
std::string key{}; META_MODE, META_MODIFIED, META_OSXFLAGS, META_PINNED,
std::uint64_t modified_date{}; META_SIZE, META_SOURCE, META_UID, META_WRITTEN,
std::string source_path; };
};
using api_meta_map = std::map<std::string, std::string>;
struct directory_item final {
std::string api_path{}; enum class api_error {
std::string api_parent{}; success = 0,
bool directory{false}; access_denied,
std::uint64_t size{}; bad_address,
api_meta_map meta{}; buffer_overflow,
bool resolved{false}; buffer_too_small,
cache_not_initialized,
[[nodiscard]] static auto from_json(const json &item) -> directory_item { comm_error,
directory_item ret{}; decryption_error,
ret.api_path = item["path"].get<std::string>(); directory_end_of_files,
ret.api_parent = item["parent"].get<std::string>(); directory_exists,
ret.directory = item["directory"].get<bool>(); directory_not_empty,
ret.size = item["size"].get<std::uint64_t>(); directory_not_found,
ret.meta = item["meta"].get<api_meta_map>(); download_failed,
return ret; download_incomplete,
} download_stopped,
empty_ring_buffer_chunk_size,
[[nodiscard]] auto to_json() const -> json { empty_ring_buffer_size,
return { error,
{"path", api_path}, {"parent", api_parent}, {"size", size}, file_in_use,
{"directory", directory}, {"meta", meta}, file_size_mismatch,
}; incompatible_version,
} invalid_handle,
}; invalid_operation,
invalid_ring_buffer_multiple,
struct encrypt_config final { invalid_ring_buffer_position,
std::string encryption_token{}; invalid_ring_buffer_size,
std::string path{}; invalid_version,
}; item_exists,
item_not_found,
struct filesystem_item final { more_data,
std::string api_path{}; no_disk_space,
std::string api_parent{}; not_implemented,
bool directory{false}; not_supported,
std::uint64_t size{}; os_error,
std::string source_path{}; out_of_memory,
}; permission_denied,
upload_failed,
struct host_config final { xattr_buffer_small,
std::string agent_string{}; xattr_exists,
std::string api_password{}; xattr_not_found,
std::string api_user{}; xattr_too_big,
std::uint16_t api_port{}; ERROR_COUNT
std::string host_name_or_ip{"localhost"}; };
std::string path{};
std::string protocol{"http"}; [[nodiscard]] auto api_error_from_string(std::string_view str) -> api_error;
std::uint32_t timeout_ms{60000U};
[[nodiscard]] auto
auto operator==(const host_config &hc) const noexcept -> bool { api_error_to_string(const api_error &error) -> const std::string &;
if (&hc != this) {
return agent_string == hc.agent_string && enum class database_type {
api_password == hc.api_password && api_user == hc.api_user && rocksdb,
api_port == hc.api_port && host_name_or_ip == hc.host_name_or_ip && sqlite,
path == hc.path && protocol == hc.protocol && };
timeout_ms == hc.timeout_ms; [[nodiscard]] auto database_type_from_string(
} std::string type,
return true; database_type default_type = database_type::rocksdb) -> database_type;
}
[[nodiscard]] auto
auto operator!=(const host_config &hc) const noexcept -> bool { database_type_to_string(const database_type &type) -> std::string;
if (&hc != this) {
return not(hc == *this); enum class download_type {
} default_,
return false; direct,
} ring_buffer,
}; };
[[nodiscard]] auto download_type_from_string(
#if defined(__GNUG__) std::string type,
__attribute__((unused)) download_type default_type = download_type::default_) -> download_type;
#endif
static void [[nodiscard]] auto
to_json(json &j, const host_config &hc) { download_type_to_string(const download_type &type) -> std::string;
j = json{{"AgentString", hc.agent_string},
{"ApiPassword", hc.api_password}, enum class exit_code : std::int32_t {
{"ApiPort", hc.api_port}, success = 0,
{"ApiUser", hc.api_user}, communication_error = -1,
{"HostNameOrIp", hc.host_name_or_ip}, file_creation_failed = -2,
{"Path", hc.path}, incompatible_version = -3,
{"Protocol", hc.protocol}, invalid_syntax = -4,
{"TimeoutMs", hc.timeout_ms}}; lock_failed = -5,
} mount_active = -6,
mount_result = -7,
#if defined(__GNUG__) not_mounted = -8,
__attribute__((unused)) startup_exception = -9,
#endif failed_to_get_mount_state = -10,
static void export_failed = -11,
from_json(const json &j, host_config &hc) { import_failed = -12,
j.at("AgentString").get_to(hc.agent_string); option_not_found = -13,
j.at("ApiPassword").get_to(hc.api_password); invalid_provider_type = -14,
j.at("ApiPort").get_to(hc.api_port); set_option_not_found = -15,
j.at("AuthUser").get_to(hc.api_user); pin_failed = -16,
j.at("HostNameOrIp").get_to(hc.host_name_or_ip); unpin_failed = -17,
j.at("Path").get_to(hc.path); init_failed = -18,
j.at("Protocol").get_to(hc.protocol); };
j.at("TimeoutMs").get_to(hc.timeout_ms);
} enum http_error_codes : std::int32_t {
ok = 200,
struct s3_config final { multiple_choices = 300,
std::string access_key{}; not_found = 404,
std::string bucket{}; };
std::string encryption_token{};
std::string region{"any"}; enum class lock_result {
std::string secret_key{}; success,
std::uint32_t timeout_ms{60000U}; locked,
std::string url{}; failure,
bool use_path_style{false}; };
bool use_region_in_url{false};
}; enum class provider_type : std::size_t {
sia,
struct sia_config final { remote,
std::string bucket{}; s3,
}; encrypt,
unknown,
using api_file_list = std::vector<api_file>; };
using api_file_provider_callback = std::function<void(api_file &)>;
using api_item_added_callback = std::function<api_error(bool, api_file &)>; #if defined(_WIN32)
using directory_item_list = std::vector<directory_item>; struct open_file_data final {
using meta_provider_callback = std::function<void(directory_item &)>; PVOID directory_buffer{nullptr};
} // namespace repertory };
#else
#endif // REPERTORY_INCLUDE_TYPES_REPERTORY_HPP_ using open_file_data = int;
#endif
struct api_file final {
std::string api_path;
std::string api_parent;
std::uint64_t accessed_date{};
std::uint64_t changed_date{};
std::uint64_t creation_date{};
std::uint64_t file_size{};
std::string key;
std::uint64_t modified_date{};
std::string source_path;
};
struct directory_item final {
std::string api_path;
std::string api_parent;
bool directory{false};
std::uint64_t size{};
api_meta_map meta;
bool resolved{false};
};
struct encrypt_config final {
std::string encryption_token;
std::string path;
auto operator==(const encrypt_config &cfg) const noexcept -> bool {
if (&cfg != this) {
return encryption_token == cfg.encryption_token && path == cfg.path;
}
return true;
}
auto operator!=(const encrypt_config &cfg) const noexcept -> bool {
if (&cfg != this) {
return not(cfg == *this);
}
return false;
}
};
struct filesystem_item final {
std::string api_path;
std::string api_parent;
bool directory{false};
std::uint64_t size{};
std::string source_path;
};
struct host_config final {
std::string agent_string;
std::string api_password;
std::string api_user;
std::uint16_t api_port;
std::string host_name_or_ip{"localhost"};
std::string path;
std::string protocol{"http"};
std::uint32_t timeout_ms{default_timeout_ms};
auto operator==(const host_config &cfg) const noexcept -> bool {
if (&cfg != this) {
return agent_string == cfg.agent_string &&
api_password == cfg.api_password && api_user == cfg.api_user &&
api_port == cfg.api_port &&
host_name_or_ip == cfg.host_name_or_ip && path == cfg.path &&
protocol == cfg.protocol && timeout_ms == cfg.timeout_ms;
}
return true;
}
auto operator!=(const host_config &cfg) const noexcept -> bool {
if (&cfg != this) {
return not(cfg == *this);
}
return false;
}
};
struct s3_config final {
std::string access_key;
std::string bucket;
std::string encryption_token;
std::string region{"any"};
std::string secret_key;
std::uint32_t timeout_ms{default_timeout_ms};
std::string url;
bool use_path_style{false};
bool use_region_in_url{false};
auto operator==(const s3_config &cfg) const noexcept -> bool {
if (&cfg != this) {
return access_key == cfg.access_key && bucket == cfg.bucket &&
encryption_token == cfg.encryption_token && region == cfg.region &&
secret_key == cfg.secret_key && timeout_ms == cfg.timeout_ms &&
url == cfg.url && use_path_style == cfg.use_path_style &&
use_region_in_url == cfg.use_region_in_url;
}
return true;
}
auto operator!=(const s3_config &cfg) const noexcept -> bool {
if (&cfg != this) {
return not(cfg == *this);
}
return false;
}
};
struct sia_config final {
std::string bucket;
auto operator==(const sia_config &cfg) const noexcept -> bool {
if (&cfg != this) {
return bucket == cfg.bucket;
}
return true;
}
auto operator!=(const sia_config &cfg) const noexcept -> bool {
if (&cfg != this) {
return not(cfg == *this);
}
return false;
}
};
using api_file_list = std::vector<api_file>;
using api_file_provider_callback = std::function<void(api_file &)>;
using api_item_added_callback = std::function<api_error(bool, api_file &)>;
using directory_item_list = std::vector<directory_item>;
using meta_provider_callback = std::function<void(directory_item &)>;
inline constexpr const auto JSON_ACCESS_KEY{"AccessKey"};
inline constexpr const auto JSON_AGENT_STRING{"AgentString"};
inline constexpr const auto JSON_API_AUTH{"ApiAuth"};
inline constexpr const auto JSON_API_PARENT{"ApiParent"};
inline constexpr const auto JSON_API_PASSWORD{"ApiPassword"};
inline constexpr const auto JSON_API_PATH{"ApiPath"};
inline constexpr const auto JSON_API_PORT{"ApiPort"};
inline constexpr const auto JSON_API_USER{"ApiUser"};
inline constexpr const auto JSON_BUCKET{"Bucket"};
inline constexpr const auto JSON_CLIENT_POOL_SIZE{"ClientPoolSize"};
inline constexpr const auto JSON_DATABASE_TYPE{"DatabaseType"};
inline constexpr const auto JSON_DIRECTORY{"Directory"};
inline constexpr const auto JSON_DOWNLOAD_TIMEOUT_SECS{
"DownloadTimeoutSeconds"};
inline constexpr const auto JSON_ENABLE_DRIVE_EVENTS{"EnableDriveEvents"};
inline constexpr const auto JSON_ENABLE_DOWNLOAD_TIMEOUT{
"EnableDownloadTimeout"};
inline constexpr const auto JSON_ENABLE_MOUNT_MANAGER{"EnableMountManager"};
inline constexpr const auto JSON_ENABLE_REMOTE_MOUNT{"Enable"};
inline constexpr const auto JSON_ENCRYPTION_TOKEN{"EncryptionToken"};
inline constexpr const auto JSON_ENCRYPT_CONFIG{"EncryptConfig"};
inline constexpr const auto JSON_EVENT_LEVEL{"EventLevel"};
inline constexpr const auto JSON_EVICTION_DELAY_MINS{"EvictionDelayMinutes"};
inline constexpr const auto JSON_EVICTION_USE_ACCESS_TIME{
"EvictionUseAccessedTime"};
inline constexpr const auto JSON_HIGH_FREQ_INTERVAL_SECS{
"HighFreqIntervalSeconds"};
inline constexpr const auto JSON_HOST_CONFIG{"HostConfig"};
inline constexpr const auto JSON_HOST_NAME_OR_IP{"HostNameOrIp"};
inline constexpr const auto JSON_LOW_FREQ_INTERVAL_SECS{
"LowFreqIntervalSeconds"};
inline constexpr const auto JSON_MAX_CACHE_SIZE_BYTES{"MaxCacheSizeBytes"};
inline constexpr const auto JSON_MAX_CONNECTIONS{"MaxConnections"};
inline constexpr const auto JSON_MAX_UPLOAD_COUNT{"MaxUploadCount"};
inline constexpr const auto JSON_MED_FREQ_INTERVAL_SECS{
"MedFreqIntervalSeconds"};
inline constexpr const auto JSON_META{"Meta"};
inline constexpr const auto JSON_ONLINE_CHECK_RETRY_SECS{
"OnlineCheckRetrySeconds"};
inline constexpr const auto JSON_ORPHANED_FILE_RETENTION_DAYS{
"OrphanedFileRetentionDays"};
inline constexpr const auto JSON_PATH{"Path"};
inline constexpr const auto JSON_PREFERRED_DOWNLOAD_TYPE{
"PreferredDownloadType"};
inline constexpr const auto JSON_PROTOCOL{"Protocol"};
inline constexpr const auto JSON_RECV_TIMEOUT_MS{"ReceiveTimeoutMs"};
inline constexpr const auto JSON_REGION{"Region"};
inline constexpr const auto JSON_REMOTE_CONFIG{"RemoteConfig"};
inline constexpr const auto JSON_REMOTE_MOUNT{"RemoteMount"};
inline constexpr const auto JSON_RETRY_READ_COUNT{"RetryReadCount"};
inline constexpr const auto JSON_RING_BUFFER_FILE_SIZE{"RingBufferFileSize"};
inline constexpr const auto JSON_S3_CONFIG{"S3Config"};
inline constexpr const auto JSON_SECRET_KEY{"SecretKey"};
inline constexpr const auto JSON_SEND_TIMEOUT_MS{"SendTimeoutMs"};
inline constexpr const auto JSON_SIA_CONFIG{"SiaConfig"};
inline constexpr const auto JSON_SIZE{"Size"};
inline constexpr const auto JSON_TASK_WAIT_MS{"TaskWaitMs"};
inline constexpr const auto JSON_TIMEOUT_MS{"TimeoutMs"};
inline constexpr const auto JSON_URL{"URL"};
inline constexpr const auto JSON_USE_PATH_STYLE{"UsePathStyle"};
inline constexpr const auto JSON_USE_REGION_IN_URL{"UseRegionInURL"};
inline constexpr const auto JSON_VERSION{"Version"};
} // namespace repertory
NLOHMANN_JSON_NAMESPACE_BEGIN
template <> struct adl_serializer<repertory::directory_item> {
static void to_json(json &data, const repertory::directory_item &value) {
data[repertory::JSON_API_PARENT] = value.api_parent;
data[repertory::JSON_API_PATH] = value.api_path;
data[repertory::JSON_DIRECTORY] = value.directory;
data[repertory::JSON_META] = value.meta;
data[repertory::JSON_SIZE] = value.size;
}
static void from_json(const json &data, repertory::directory_item &value) {
data.at(repertory::JSON_API_PARENT).get_to<std::string>(value.api_parent);
data.at(repertory::JSON_API_PATH).get_to<std::string>(value.api_path);
data.at(repertory::JSON_DIRECTORY).get_to<bool>(value.directory);
data.at(repertory::JSON_META).get_to<repertory::api_meta_map>(value.meta);
data.at(repertory::JSON_SIZE).get_to<std::uint64_t>(value.size);
}
};
template <> struct adl_serializer<repertory::encrypt_config> {
static void to_json(json &data, const repertory::encrypt_config &value) {
data[repertory::JSON_ENCRYPTION_TOKEN] = value.encryption_token;
data[repertory::JSON_PATH] = value.path;
}
static void from_json(const json &data, repertory::encrypt_config &value) {
data.at(repertory::JSON_ENCRYPTION_TOKEN).get_to(value.encryption_token);
data.at(repertory::JSON_PATH).get_to(value.path);
}
};
template <> struct adl_serializer<repertory::host_config> {
static void to_json(json &data, const repertory::host_config &value) {
data[repertory::JSON_AGENT_STRING] = value.agent_string;
data[repertory::JSON_API_PASSWORD] = value.api_password;
data[repertory::JSON_API_PORT] = value.api_port;
data[repertory::JSON_API_USER] = value.api_user;
data[repertory::JSON_HOST_NAME_OR_IP] = value.host_name_or_ip;
data[repertory::JSON_PATH] = value.path;
data[repertory::JSON_PROTOCOL] = value.protocol;
data[repertory::JSON_TIMEOUT_MS] = value.timeout_ms;
}
static void from_json(const json &data, repertory::host_config &value) {
data.at(repertory::JSON_AGENT_STRING).get_to(value.agent_string);
data.at(repertory::JSON_API_PASSWORD).get_to(value.api_password);
data.at(repertory::JSON_API_PORT).get_to(value.api_port);
data.at(repertory::JSON_API_USER).get_to(value.api_user);
data.at(repertory::JSON_HOST_NAME_OR_IP).get_to(value.host_name_or_ip);
data.at(repertory::JSON_PATH).get_to(value.path);
data.at(repertory::JSON_PROTOCOL).get_to(value.protocol);
data.at(repertory::JSON_TIMEOUT_MS).get_to(value.timeout_ms);
}
};
template <> struct adl_serializer<repertory::s3_config> {
static void to_json(json &data, const repertory::s3_config &value) {
data[repertory::JSON_ACCESS_KEY] = value.access_key;
data[repertory::JSON_BUCKET] = value.bucket;
data[repertory::JSON_ENCRYPTION_TOKEN] = value.encryption_token;
data[repertory::JSON_REGION] = value.region;
data[repertory::JSON_SECRET_KEY] = value.secret_key;
data[repertory::JSON_TIMEOUT_MS] = value.timeout_ms;
data[repertory::JSON_URL] = value.url;
data[repertory::JSON_USE_PATH_STYLE] = value.use_path_style;
data[repertory::JSON_USE_REGION_IN_URL] = value.use_region_in_url;
}
static void from_json(const json &data, repertory::s3_config &value) {
data.at(repertory::JSON_ACCESS_KEY).get_to(value.access_key);
data.at(repertory::JSON_BUCKET).get_to(value.bucket);
data.at(repertory::JSON_ENCRYPTION_TOKEN).get_to(value.encryption_token);
data.at(repertory::JSON_REGION).get_to(value.region);
data.at(repertory::JSON_SECRET_KEY).get_to(value.secret_key);
data.at(repertory::JSON_TIMEOUT_MS).get_to(value.timeout_ms);
data.at(repertory::JSON_URL).get_to(value.url);
data.at(repertory::JSON_USE_PATH_STYLE).get_to(value.use_path_style);
data.at(repertory::JSON_USE_REGION_IN_URL).get_to(value.use_region_in_url);
}
};
template <> struct adl_serializer<repertory::sia_config> {
static void to_json(json &data, const repertory::sia_config &value) {
data[repertory::JSON_BUCKET] = value.bucket;
}
static void from_json(const json &data, repertory::sia_config &value) {
data.at(repertory::JSON_BUCKET).get_to(value.bucket);
}
};
template <typename data_t> struct adl_serializer<repertory::atomic<data_t>> {
static void to_json(json &data, const repertory::atomic<data_t> &value) {
data = value.load();
}
static void from_json(const json &data, repertory::atomic<data_t> &value) {
value.store(data.get<data_t>());
}
};
template <typename primitive_t>
struct adl_serializer<std::atomic<primitive_t>> {
static void to_json(json &data, const std::atomic<primitive_t> &value) {
data = value.load();
}
static void from_json(const json &data, std::atomic<primitive_t> &value) {
value.store(data.get<primitive_t>());
}
};
template <> struct adl_serializer<std::atomic<repertory::database_type>> {
static void to_json(json &data,
const std::atomic<repertory::database_type> &value) {
data = repertory::database_type_to_string(value.load());
}
static void from_json(const json &data,
std::atomic<repertory::database_type> &value) {
value.store(repertory::database_type_from_string(data.get<std::string>()));
}
};
template <> struct adl_serializer<std::atomic<repertory::download_type>> {
static void to_json(json &data,
const std::atomic<repertory::download_type> &value) {
data = repertory::download_type_to_string(value.load());
}
static void from_json(const json &data,
std::atomic<repertory::download_type> &value) {
value.store(repertory::download_type_from_string(data.get<std::string>()));
}
};
template <> struct adl_serializer<repertory::database_type> {
static void to_json(json &data, const repertory::database_type &value) {
data = repertory::database_type_to_string(value);
}
static void from_json(const json &data, repertory::database_type &value) {
value = repertory::database_type_from_string(data.get<std::string>());
}
};
template <> struct adl_serializer<repertory::download_type> {
static void to_json(json &data, const repertory::download_type &value) {
data = repertory::download_type_to_string(value);
}
static void from_json(const json &data, repertory::download_type &value) {
value = repertory::download_type_from_string(data.get<std::string>());
}
};
NLOHMANN_JSON_NAMESPACE_END
#endif // REPERTORY_INCLUDE_TYPES_REPERTORY_HPP_

View File

@ -26,18 +26,21 @@
namespace repertory { namespace repertory {
class app_config; class app_config;
class polling final { class polling final {
public: public:
enum struct frequency { enum struct frequency {
high, high,
low, low,
medium,
second, second,
size,
}; };
struct polling_item { struct polling_item final {
std::string name; std::string name;
frequency freq; frequency freq;
std::function<void()> action; std::function<void(const stop_type &stop_requested)> action;
}; };
public: public:
@ -58,15 +61,15 @@ public:
static auto instance() -> polling & { return instance_; } static auto instance() -> polling & { return instance_; }
private: private:
app_config *config_ = nullptr; app_config *config_{nullptr};
std::unique_ptr<std::thread> high_frequency_thread_; std::array<std::unique_ptr<std::thread>,
static_cast<std::size_t>(frequency::size)>
frequency_threads_;
std::unordered_map<std::string, polling_item> items_; std::unordered_map<std::string, polling_item> items_;
std::unique_ptr<std::thread> low_frequency_thread_;
std::mutex mutex_; std::mutex mutex_;
std::condition_variable notify_; std::condition_variable notify_;
std::unique_ptr<std::thread> second_frequency_thread_;
std::mutex start_stop_mutex_; std::mutex start_stop_mutex_;
stop_type stop_requested_ = false; stop_type stop_requested_{false};
private: private:
void frequency_thread(std::function<std::uint32_t()> get_frequency_seconds, void frequency_thread(std::function<std::uint32_t()> get_frequency_seconds,

View File

@ -0,0 +1,116 @@
/*
Copyright <2018-2024> <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 REPERTORY_INCLUDE_UTILS_TASKS_HPP_
#define REPERTORY_INCLUDE_UTILS_TASKS_HPP_
#include "common.hpp"
namespace repertory {
class app_config;
class tasks final {
public:
struct task final {
std::function<void(const stop_type &task_stopped)> action;
};
class i_task {
INTERFACE_SETUP(i_task);
public:
virtual auto wait() const -> bool = 0;
};
using task_ptr = std::shared_ptr<i_task>;
private:
class task_wait final : public i_task {
public:
task_wait() = default;
task_wait(const task_wait &) = delete;
task_wait(task_wait &&) = delete;
~task_wait() override { set_result(false); }
auto operator=(const task_wait &) -> task_wait & = delete;
auto operator=(task_wait &&) -> task_wait & = delete;
private:
bool complete{false};
mutable std::mutex mtx;
mutable std::condition_variable notify;
bool success{false};
public:
void set_result(bool result);
auto wait() const -> bool override;
};
struct scheduled_task final {
task item;
std::shared_ptr<task_wait> wait{
std::make_shared<task_wait>(),
};
};
public:
tasks(const tasks &) = delete;
tasks(tasks &&) = delete;
auto operator=(const tasks &) -> tasks & = delete;
auto operator=(tasks &&) -> tasks & = delete;
private:
tasks() = default;
~tasks() { stop(); }
private:
static tasks instance_;
public:
static auto instance() -> tasks & { return instance_; }
private:
app_config *config_{nullptr};
std::atomic<std::uint64_t> count_{0U};
std::mutex mutex_;
std::condition_variable notify_;
std::mutex start_stop_mutex_;
stop_type stop_requested_{false};
std::vector<std::unique_ptr<std::jthread>> task_threads_;
std::deque<scheduled_task> tasks_;
private:
void task_thread();
public:
auto schedule(task item) -> task_ptr;
void start(app_config *config);
void stop();
};
} // namespace repertory
#endif // REPERTORY_INCLUDE_UTILS_TASKS_HPP_

View File

@ -24,15 +24,25 @@
#include "types/repertory.hpp" #include "types/repertory.hpp"
namespace repertory::utils { namespace repertory {
class app_config;
namespace utils {
void calculate_allocation_size(bool directory, std::uint64_t file_size, void calculate_allocation_size(bool directory, std::uint64_t file_size,
UINT64 allocation_size, UINT64 allocation_size,
std::string &allocation_meta_size); std::string &allocation_meta_size);
[[nodiscard]] auto [[nodiscard]] auto
create_volume_label(const provider_type &prov) -> std::string; create_rocksdb(const app_config &cfg, const std::string &name,
const std::vector<rocksdb::ColumnFamilyDescriptor> &families,
std::vector<rocksdb::ColumnFamilyHandle *> &handles, bool clear)
-> std::unique_ptr<rocksdb::TransactionDB>;
[[nodiscard]] auto create_volume_label(const provider_type &prov)
-> std::string;
[[nodiscard]] auto get_attributes_from_meta(const api_meta_map &meta) -> DWORD; [[nodiscard]] auto get_attributes_from_meta(const api_meta_map &meta) -> DWORD;
} // namespace repertory::utils } // namespace utils
} // namespace repertory
#endif // REPERTORY_INCLUDE_UTILS_UTILS_HPP_ #endif // REPERTORY_INCLUDE_UTILS_UTILS_HPP_

File diff suppressed because it is too large Load Diff

View File

@ -21,16 +21,19 @@
*/ */
#include "comm/curl/requests/http_put_file.hpp" #include "comm/curl/requests/http_put_file.hpp"
#include "utils/error_utils.hpp"
#include "utils/string.hpp" #include "utils/string.hpp"
namespace repertory::curl::requests { namespace repertory::curl::requests {
auto http_put_file::set_method(CURL *curl, auto http_put_file::set_method(CURL *curl, stop_type &stop_requested) const
stop_type &stop_requested) const -> bool { -> bool {
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); REPERTORY_USES_FUNCTION_NAME();
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curl, CURLOPT_INFILE, nullptr);
if (source_path.empty()) { if (source_path.empty()) {
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, 0L); curl_easy_setopt(curl, CURLOPT_INFILESIZE, 0L);
return true; return true;
} }
@ -49,14 +52,28 @@ auto http_put_file::set_method(CURL *curl,
utils::file::file::open_or_create_file(source_path), utils::file::file::open_or_create_file(source_path),
}); });
if (not *read_info->file) { if (not*read_info->file) {
utils::error::raise_url_error(function_name, get_path(), source_path,
std::runtime_error("failed to open file"));
return false; return false;
} }
auto file_size = read_info->file->size(); auto opt_size = read_info->file->size();
if (not opt_size.has_value()) {
utils::error::raise_url_error(
function_name, get_path(), source_path,
std::runtime_error("failed to get file size"));
return false;
}
auto file_size = opt_size.value();
if (file_size == 0U) {
curl_easy_setopt(curl, CURLOPT_INFILESIZE, 0L);
return true;
}
curl_easy_setopt(curl, CURLOPT_READDATA, read_info.get()); curl_easy_setopt(curl, CURLOPT_READDATA, read_info.get());
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_file_data); curl_easy_setopt(curl, CURLOPT_READFUNCTION, curl_file_reader);
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, file_size); curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, file_size);
return true; return true;

View File

@ -0,0 +1,43 @@
/*
Copyright <2018-2024> <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.
*/
#include "comm/curl/requests/http_request_base.hpp"
#include "utils/file.hpp"
#include "utils/string.hpp"
namespace repertory::curl::requests {
auto curl_file_reader(char *buffer, size_t size, size_t nitems, void *instream)
-> size_t {
auto *read_info = reinterpret_cast<read_file_info *>(instream);
std::size_t bytes_read{};
auto ret =
read_info->file->read(reinterpret_cast<unsigned char *>(buffer),
size * nitems, read_info->offset, &bytes_read);
if (ret) {
read_info->offset += bytes_read;
}
return ret && not read_info->stop_requested ? bytes_read
: CURL_READFUNC_ABORT;
}
} // namespace repertory::curl::requests

View File

@ -30,7 +30,7 @@ namespace repertory {
void client_pool::pool::execute( void client_pool::pool::execute(
std::uint64_t thread_id, const worker_callback &worker, std::uint64_t thread_id, const worker_callback &worker,
const worker_complete_callback &worker_complete) { const worker_complete_callback &worker_complete) {
const auto index = thread_id % pool_queues_.size(); auto index = thread_id % pool_queues_.size();
auto job = std::make_shared<work_item>(worker, worker_complete); auto job = std::make_shared<work_item>(worker, worker_complete);
auto &pool_queue = pool_queues_[index]; auto &pool_queue = pool_queues_[index];
@ -41,9 +41,7 @@ void client_pool::pool::execute(
} }
client_pool::pool::pool(std::uint8_t pool_size) { client_pool::pool::pool(std::uint8_t pool_size) {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
event_system::instance().raise<service_started>("client_pool"); event_system::instance().raise<service_started>("client_pool");
@ -53,7 +51,7 @@ client_pool::pool::pool(std::uint8_t pool_size) {
for (std::size_t i = 0U; i < pool_queues_.size(); i++) { for (std::size_t i = 0U; i < pool_queues_.size(); i++) {
pool_threads_.emplace_back([this]() { pool_threads_.emplace_back([this]() {
const auto thread_index = thread_index_++; auto thread_index = thread_index_++;
auto &pool_queue = pool_queues_[thread_index]; auto &pool_queue = pool_queues_[thread_index];
auto &queue = pool_queue->queue; auto &queue = pool_queue->queue;
@ -76,7 +74,7 @@ client_pool::pool::pool(std::uint8_t pool_size) {
queue_lock.unlock(); queue_lock.unlock();
try { try {
const auto result = item->work(); auto result = item->work();
item->work_complete(result); item->work_complete(result);
} catch (const std::exception &e) { } catch (const std::exception &e) {
item->work_complete(utils::from_api_error(api_error::error)); item->work_complete(utils::from_api_error(api_error::error));

View File

@ -36,8 +36,8 @@ void packet::clear() {
} }
auto packet::decode(std::string &data) -> packet::error_type { auto packet::decode(std::string &data) -> packet::error_type {
const auto *str = reinterpret_cast<const char *>(&buffer_[decode_offset_]); const auto *str = reinterpret_cast<const char *>(&buffer_.at(decode_offset_));
const auto length = strnlen(str, buffer_.size() - decode_offset_); auto length = strnlen(str, buffer_.size() - decode_offset_);
data = std::string(str, length); data = std::string(str, length);
decode_offset_ += (length + 1); decode_offset_ += (length + 1);
@ -46,7 +46,7 @@ auto packet::decode(std::string &data) -> packet::error_type {
auto packet::decode(std::wstring &data) -> packet::error_type { auto packet::decode(std::wstring &data) -> packet::error_type {
std::string utf8_string; std::string utf8_string;
const auto ret = decode(utf8_string); auto ret = decode(utf8_string);
if (ret == 0) { if (ret == 0) {
data = utils::string::from_utf8(utf8_string); data = utils::string::from_utf8(utf8_string);
} }
@ -60,7 +60,7 @@ auto packet::decode(void *&ptr) -> packet::error_type {
auto packet::decode(void *buffer, std::size_t size) -> packet::error_type { auto packet::decode(void *buffer, std::size_t size) -> packet::error_type {
if (size != 0U) { if (size != 0U) {
const auto read_size = auto read_size =
utils::calculate_read_size(buffer_.size(), size, decode_offset_); utils::calculate_read_size(buffer_.size(), size, decode_offset_);
if (read_size == size) { if (read_size == size) {
memcpy(buffer, &buffer_[decode_offset_], size); memcpy(buffer, &buffer_[decode_offset_], size);
@ -76,7 +76,7 @@ auto packet::decode(void *buffer, std::size_t size) -> packet::error_type {
} }
auto packet::decode(std::int8_t &val) -> packet::error_type { auto packet::decode(std::int8_t &val) -> packet::error_type {
const auto ret = decode(&val, sizeof(val)); auto ret = decode(&val, sizeof(val));
if (ret == 0) { if (ret == 0) {
boost::endian::big_to_native_inplace(val); boost::endian::big_to_native_inplace(val);
} }
@ -84,7 +84,7 @@ auto packet::decode(std::int8_t &val) -> packet::error_type {
} }
auto packet::decode(std::uint8_t &val) -> packet::error_type { auto packet::decode(std::uint8_t &val) -> packet::error_type {
const auto ret = decode(&val, sizeof(val)); auto ret = decode(&val, sizeof(val));
if (ret == 0) { if (ret == 0) {
boost::endian::big_to_native_inplace(val); boost::endian::big_to_native_inplace(val);
} }
@ -92,7 +92,7 @@ auto packet::decode(std::uint8_t &val) -> packet::error_type {
} }
auto packet::decode(std::int16_t &val) -> packet::error_type { auto packet::decode(std::int16_t &val) -> packet::error_type {
const auto ret = decode(&val, sizeof(val)); auto ret = decode(&val, sizeof(val));
if (ret == 0) { if (ret == 0) {
boost::endian::big_to_native_inplace(val); boost::endian::big_to_native_inplace(val);
} }
@ -100,7 +100,7 @@ auto packet::decode(std::int16_t &val) -> packet::error_type {
} }
auto packet::decode(std::uint16_t &val) -> packet::error_type { auto packet::decode(std::uint16_t &val) -> packet::error_type {
const auto ret = decode(&val, sizeof(val)); auto ret = decode(&val, sizeof(val));
if (ret == 0) { if (ret == 0) {
boost::endian::big_to_native_inplace(val); boost::endian::big_to_native_inplace(val);
} }
@ -108,7 +108,7 @@ auto packet::decode(std::uint16_t &val) -> packet::error_type {
} }
auto packet::decode(std::int32_t &val) -> packet::error_type { auto packet::decode(std::int32_t &val) -> packet::error_type {
const auto ret = decode(&val, sizeof(val)); auto ret = decode(&val, sizeof(val));
if (ret == 0) { if (ret == 0) {
boost::endian::big_to_native_inplace(val); boost::endian::big_to_native_inplace(val);
} }
@ -116,7 +116,7 @@ auto packet::decode(std::int32_t &val) -> packet::error_type {
} }
auto packet::decode(std::uint32_t &val) -> packet::error_type { auto packet::decode(std::uint32_t &val) -> packet::error_type {
const auto ret = decode(&val, sizeof(val)); auto ret = decode(&val, sizeof(val));
if (ret == 0) { if (ret == 0) {
boost::endian::big_to_native_inplace(val); boost::endian::big_to_native_inplace(val);
} }
@ -124,7 +124,7 @@ auto packet::decode(std::uint32_t &val) -> packet::error_type {
} }
auto packet::decode(std::int64_t &val) -> packet::error_type { auto packet::decode(std::int64_t &val) -> packet::error_type {
const auto ret = decode(&val, sizeof(val)); auto ret = decode(&val, sizeof(val));
if (ret == 0) { if (ret == 0) {
boost::endian::big_to_native_inplace(val); boost::endian::big_to_native_inplace(val);
} }
@ -132,7 +132,7 @@ auto packet::decode(std::int64_t &val) -> packet::error_type {
} }
auto packet::decode(std::uint64_t &val) -> packet::error_type { auto packet::decode(std::uint64_t &val) -> packet::error_type {
const auto ret = decode(&val, sizeof(val)); auto ret = decode(&val, sizeof(val));
if (ret == 0) { if (ret == 0) {
boost::endian::big_to_native_inplace(val); boost::endian::big_to_native_inplace(val);
} }
@ -140,7 +140,7 @@ auto packet::decode(std::uint64_t &val) -> packet::error_type {
} }
auto packet::decode(remote::setattr_x &val) -> packet::error_type { auto packet::decode(remote::setattr_x &val) -> packet::error_type {
const auto ret = decode(&val, sizeof(val)); auto ret = decode(&val, sizeof(val));
if (ret == 0) { if (ret == 0) {
boost::endian::big_to_native_inplace(val.acctime); boost::endian::big_to_native_inplace(val.acctime);
boost::endian::big_to_native_inplace(val.bkuptime); boost::endian::big_to_native_inplace(val.bkuptime);
@ -159,7 +159,7 @@ auto packet::decode(remote::setattr_x &val) -> packet::error_type {
} }
auto packet::decode(remote::stat &val) -> packet::error_type { auto packet::decode(remote::stat &val) -> packet::error_type {
const auto ret = decode(&val, sizeof(val)); auto ret = decode(&val, sizeof(val));
if (ret == 0) { if (ret == 0) {
boost::endian::big_to_native_inplace(val.st_mode); boost::endian::big_to_native_inplace(val.st_mode);
boost::endian::big_to_native_inplace(val.st_nlink); boost::endian::big_to_native_inplace(val.st_nlink);
@ -179,7 +179,7 @@ auto packet::decode(remote::stat &val) -> packet::error_type {
} }
auto packet::decode(remote::statfs &val) -> packet::error_type { auto packet::decode(remote::statfs &val) -> packet::error_type {
const auto ret = decode(&val, sizeof(val)); auto ret = decode(&val, sizeof(val));
if (ret == 0) { if (ret == 0) {
boost::endian::big_to_native_inplace(val.f_bavail); boost::endian::big_to_native_inplace(val.f_bavail);
boost::endian::big_to_native_inplace(val.f_bfree); boost::endian::big_to_native_inplace(val.f_bfree);
@ -200,7 +200,7 @@ auto packet::decode(remote::statfs_x &val) -> packet::error_type {
} }
auto packet::decode(remote::file_info &val) -> packet::error_type { auto packet::decode(remote::file_info &val) -> packet::error_type {
const auto ret = decode(&val, sizeof(val)); auto ret = decode(&val, sizeof(val));
if (ret == 0) { if (ret == 0) {
boost::endian::big_to_native_inplace(val.AllocationSize); boost::endian::big_to_native_inplace(val.AllocationSize);
boost::endian::big_to_native_inplace(val.ChangeTime); boost::endian::big_to_native_inplace(val.ChangeTime);
@ -219,9 +219,7 @@ auto packet::decode(remote::file_info &val) -> packet::error_type {
} }
auto packet::decode_json(packet &response, json &json_data) -> int { auto packet::decode_json(packet &response, json &json_data) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
std::string data; std::string data;
auto ret = response.decode(data); auto ret = response.decode(data);
@ -239,9 +237,7 @@ auto packet::decode_json(packet &response, json &json_data) -> int {
} }
auto packet::decrypt(std::string_view token) -> packet::error_type { auto packet::decrypt(std::string_view token) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
auto ret = utils::from_api_error(api_error::success); auto ret = utils::from_api_error(api_error::success);
try { try {
@ -272,7 +268,7 @@ void packet::encode(const void *buffer, std::size_t size, bool should_reserve) {
} }
void packet::encode(std::string_view str) { void packet::encode(std::string_view str) {
const auto len = str.size(); auto len = str.size();
buffer_.reserve(len + 1 + buffer_.size()); buffer_.reserve(len + 1 + buffer_.size());
encode(str.data(), len, false); encode(str.data(), len, false);
buffer_.emplace_back(0); buffer_.emplace_back(0);
@ -405,7 +401,7 @@ void packet::encode_top(const void *buffer, std::size_t size,
} }
void packet::encode_top(std::string_view str) { void packet::encode_top(std::string_view str) {
const auto len = str.size(); auto len = str.size();
buffer_.reserve(len + 1U + buffer_.size()); buffer_.reserve(len + 1U + buffer_.size());
encode_top(str.data(), len, false); encode_top(str.data(), len, false);
buffer_.insert(buffer_.begin() + static_cast<std::int32_t>(len), 0); buffer_.insert(buffer_.begin() + static_cast<std::int32_t>(len), 0);
@ -523,9 +519,7 @@ void packet::encode_top(remote::file_info val) {
} }
void packet::encrypt(std::string_view token) { void packet::encrypt(std::string_view token) {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
try { try {
data_buffer result; data_buffer result;
@ -537,7 +531,7 @@ void packet::encrypt(std::string_view token) {
} }
} }
void packet::transfer_into(data_buffer &buffer) { void packet::to_buffer(data_buffer &buffer) {
buffer = std::move(buffer_); buffer = std::move(buffer_);
buffer_ = data_buffer(); buffer_ = data_buffer();
decode_offset_ = 0; decode_offset_ = 0;

View File

@ -38,18 +38,8 @@ E_SIMPLE2(packet_client_timeout, error, true,
); );
// clang-format on // clang-format on
packet_client::packet_client(std::string host_name_or_ip, packet_client::packet_client(remote::remote_config cfg)
std::uint8_t max_connections, std::uint16_t port, : cfg_(std::move(cfg)), unique_id_(utils::create_uuid_string()) {}
std::uint16_t receive_timeout,
std::uint16_t send_timeout,
std::string encryption_token)
: host_name_or_ip_(std::move(host_name_or_ip)),
max_connections_(max_connections == 0U ? 20U : max_connections),
port_(port),
receive_timeout_(receive_timeout),
send_timeout_(send_timeout),
encryption_token_(std::move(encryption_token)),
unique_id_(utils::create_uuid_string()) {}
packet_client::~packet_client() { packet_client::~packet_client() {
allow_connections_ = false; allow_connections_ = false;
@ -76,9 +66,7 @@ void packet_client::close_all() {
} }
void packet_client::connect(client &cli) { void packet_client::connect(client &cli) {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
try { try {
resolve(); resolve();
@ -87,7 +75,7 @@ void packet_client::connect(client &cli) {
cli.socket.set_option(boost::asio::socket_base::linger(false, 0)); cli.socket.set_option(boost::asio::socket_base::linger(false, 0));
packet response; packet response;
const auto res = read_packet(cli, response); auto res = read_packet(cli, response);
if (res != 0) { if (res != 0) {
throw std::runtime_error(std::to_string(res)); throw std::runtime_error(std::to_string(res));
} }
@ -97,38 +85,38 @@ void packet_client::connect(client &cli) {
} }
auto packet_client::get_client() -> std::shared_ptr<packet_client::client> { auto packet_client::get_client() -> std::shared_ptr<packet_client::client> {
std::shared_ptr<client> ret;
unique_mutex_lock clients_lock(clients_mutex_); unique_mutex_lock clients_lock(clients_mutex_);
if (allow_connections_) { if (not allow_connections_) {
if (clients_.empty()) { return nullptr;
clients_lock.unlock();
ret = std::make_shared<client>(io_context_);
connect(*ret);
} else {
ret = clients_[0U];
utils::collection::remove_element(clients_, ret);
clients_lock.unlock();
}
} }
return ret; if (clients_.empty()) {
clients_lock.unlock();
auto cli = std::make_shared<client>(io_context_);
connect(*cli);
return cli;
}
auto cli = clients_.at(0U);
utils::collection::remove_element(clients_, cli);
return cli;
} }
void packet_client::put_client(std::shared_ptr<client> &cli) { void packet_client::put_client(std::shared_ptr<client> &cli) {
mutex_lock clientsLock(clients_mutex_); mutex_lock clientsLock(clients_mutex_);
if (clients_.size() < max_connections_) { if (clients_.size() < cfg_.max_connections) {
clients_.emplace_back(cli); clients_.emplace_back(cli);
} }
} }
auto packet_client::read_packet(client &cli, auto packet_client::read_packet(client &cli, packet &response)
packet &response) -> packet::error_type { -> packet::error_type {
data_buffer buffer(sizeof(std::uint32_t)); data_buffer buffer(sizeof(std::uint32_t));
const auto read_buffer = [&]() { const auto read_buffer = [&]() {
std::uint32_t offset{}; std::uint32_t offset{};
while (offset < buffer.size()) { while (offset < buffer.size()) {
const auto bytes_read = boost::asio::read( auto bytes_read = boost::asio::read(
cli.socket, cli.socket,
boost::asio::buffer(&buffer[offset], buffer.size() - offset)); boost::asio::buffer(&buffer[offset], buffer.size() - offset));
if (bytes_read <= 0) { if (bytes_read <= 0) {
@ -139,14 +127,14 @@ auto packet_client::read_packet(client &cli,
}; };
read_buffer(); read_buffer();
const auto size = boost::endian::big_to_native( auto size = boost::endian::big_to_native(
*reinterpret_cast<std::uint32_t *>(buffer.data())); *reinterpret_cast<std::uint32_t *>(buffer.data()));
buffer.resize(size); buffer.resize(size);
read_buffer(); read_buffer();
response = std::move(buffer); response = std::move(buffer);
auto ret = response.decrypt(encryption_token_); auto ret = response.decrypt(cfg_.encryption_token);
if (ret == 0) { if (ret == 0) {
ret = response.decode(cli.nonce); ret = response.decode(cli.nonce);
} }
@ -155,14 +143,17 @@ auto packet_client::read_packet(client &cli,
} }
void packet_client::resolve() { void packet_client::resolve() {
if (resolve_results_.empty()) { if (not resolve_results_.empty()) {
resolve_results_ = tcp::resolver(io_context_) return;
.resolve({host_name_or_ip_, std::to_string(port_)});
} }
resolve_results_ =
tcp::resolver(io_context_)
.resolve(cfg_.host_name_or_ip, std::to_string(cfg_.api_port));
} }
auto packet_client::send(std::string_view method, auto packet_client::send(std::string_view method, std::uint32_t &service_flags)
std::uint32_t &service_flags) -> packet::error_type { -> packet::error_type {
packet request; packet request;
return send(method, request, service_flags); return send(method, request, service_flags);
} }
@ -174,11 +165,9 @@ auto packet_client::send(std::string_view method, packet &request,
} }
auto packet_client::send(std::string_view method, packet &request, auto packet_client::send(std::string_view method, packet &request,
packet &response, packet &response, std::uint32_t &service_flags)
std::uint32_t &service_flags) -> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
auto success = false; auto success = false;
packet::error_type ret = utils::from_api_error(api_error::error); packet::error_type ret = utils::from_api_error(api_error::error);
@ -188,14 +177,14 @@ auto packet_client::send(std::string_view method, packet &request,
request.encode_top(PACKET_SERVICE_FLAGS); request.encode_top(PACKET_SERVICE_FLAGS);
request.encode_top(std::string{project_get_version()}); request.encode_top(std::string{project_get_version()});
static const std::uint8_t max_attempts{5U}; static constexpr const std::uint8_t max_attempts{5U};
for (std::uint8_t i = 1U; for (std::uint8_t i = 1U;
allow_connections_ && not success && (i <= max_attempts); i++) { allow_connections_ && not success && (i <= max_attempts); i++) {
auto current_client = get_client(); auto current_client = get_client();
if (current_client) { if (current_client) {
try { try {
request.encode_top(current_client->nonce); request.encode_top(current_client->nonce);
request.encrypt(encryption_token_); request.encrypt(cfg_.encryption_token);
timeout request_timeout( timeout request_timeout(
[method, current_client]() { [method, current_client]() {
@ -203,11 +192,11 @@ auto packet_client::send(std::string_view method, packet &request,
"request", std::string{method}); "request", std::string{method});
packet_client::close(*current_client); packet_client::close(*current_client);
}, },
std::chrono::seconds(send_timeout_)); std::chrono::milliseconds(cfg_.send_timeout_ms));
std::uint32_t offset{}; std::uint32_t offset{};
while (offset < request.get_size()) { while (offset < request.get_size()) {
const auto bytes_written = boost::asio::write( auto bytes_written = boost::asio::write(
current_client->socket, current_client->socket,
boost::asio::buffer(&request[offset], boost::asio::buffer(&request[offset],
request.get_size() - offset)); request.get_size() - offset));
@ -225,7 +214,7 @@ auto packet_client::send(std::string_view method, packet &request,
"response", std::string{method}); "response", std::string{method});
packet_client::close(*current_client); packet_client::close(*current_client);
}, },
std::chrono::seconds(receive_timeout_)); std::chrono::milliseconds(cfg_.recv_timeout_ms));
ret = read_packet(*current_client, response); ret = read_packet(*current_client, response);
response_timeout.disable(); response_timeout.disable();

View File

@ -66,15 +66,13 @@ void packet_server::add_client(connection &conn, const std::string &client_id) {
} }
void packet_server::initialize(const uint16_t &port, uint8_t pool_size) { void packet_server::initialize(const uint16_t &port, uint8_t pool_size) {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
pool_size = std::max(uint8_t(1U), pool_size); pool_size = std::max(std::uint8_t(1U), pool_size);
server_thread_ = std::make_unique<std::thread>([this, port, pool_size]() { server_thread_ = std::make_unique<std::thread>([this, port, pool_size]() {
tcp::acceptor acceptor(io_context_); tcp::acceptor acceptor(io_context_);
try { try {
const auto endpoint = tcp::endpoint(tcp::v4(), port); auto endpoint = tcp::endpoint(tcp::v4(), port);
acceptor.open(endpoint.protocol()); acceptor.open(endpoint.protocol());
acceptor.set_option(socket_base::reuse_address(true)); acceptor.set_option(socket_base::reuse_address(true));
acceptor.bind(endpoint); acceptor.bind(endpoint);
@ -105,9 +103,7 @@ void packet_server::listen_for_connection(tcp::acceptor &acceptor) {
void packet_server::on_accept(std::shared_ptr<connection> conn, void packet_server::on_accept(std::shared_ptr<connection> conn,
boost::system::error_code err) { boost::system::error_code err) {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
listen_for_connection(conn->acceptor); listen_for_connection(conn->acceptor);
if (err) { if (err) {
@ -125,9 +121,7 @@ void packet_server::on_accept(std::shared_ptr<connection> conn,
} }
void packet_server::read_header(std::shared_ptr<connection> conn) { void packet_server::read_header(std::shared_ptr<connection> conn) {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
conn->buffer.resize(sizeof(std::uint32_t)); conn->buffer.resize(sizeof(std::uint32_t));
boost::asio::async_read( boost::asio::async_read(
@ -148,15 +142,13 @@ void packet_server::read_header(std::shared_ptr<connection> conn) {
void packet_server::read_packet(std::shared_ptr<connection> conn, void packet_server::read_packet(std::shared_ptr<connection> conn,
std::uint32_t data_size) { std::uint32_t data_size) {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
try { try {
const auto read_buffer = [&]() { const auto read_buffer = [&]() {
std::uint32_t offset{}; std::uint32_t offset{};
while (offset < conn->buffer.size()) { while (offset < conn->buffer.size()) {
const auto bytes_read = boost::asio::read( auto bytes_read = boost::asio::read(
conn->socket, boost::asio::buffer(&conn->buffer[offset], conn->socket, boost::asio::buffer(&conn->buffer[offset],
conn->buffer.size() - offset)); conn->buffer.size() - offset));
if (bytes_read <= 0) { if (bytes_read <= 0) {
@ -246,15 +238,13 @@ void packet_server::remove_client(connection &conn) {
void packet_server::send_response(std::shared_ptr<connection> conn, void packet_server::send_response(std::shared_ptr<connection> conn,
const packet::error_type &result, const packet::error_type &result,
packet &response) { packet &response) {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
response.encode_top(result); response.encode_top(result);
response.encode_top(PACKET_SERVICE_FLAGS); response.encode_top(PACKET_SERVICE_FLAGS);
response.encode_top(conn->nonce); response.encode_top(conn->nonce);
response.encrypt(encryption_token_); response.encrypt(encryption_token_);
response.transfer_into(conn->buffer); response.to_buffer(conn->buffer);
boost::asio::async_write( boost::asio::async_write(
conn->socket, boost::asio::buffer(conn->buffer), conn->socket, boost::asio::buffer(conn->buffer),

View File

@ -1,41 +1,38 @@
/* /*
Copyright <2018-2024> <scott.e.graves@protonmail.com> Copyright <2018-2024> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include "file_manager/file_manager.hpp" #include "db/file_db.hpp"
namespace repertory { #include "app_config.hpp"
void file_manager::open_file_base::io_item::action() { #include "db/impl/rdb_file_db.hpp"
result_ = action_(); #include "db/impl/sqlite_file_db.hpp"
mutex_lock lock(mtx_); namespace repertory {
notify_.notify_all(); auto create_file_db(const app_config &cfg) -> std::unique_ptr<i_file_db> {
} switch (cfg.get_database_type()) {
case database_type::sqlite:
auto file_manager::open_file_base::io_item::get_result() -> api_error { return std::make_unique<sqlite_file_db>(cfg);
unique_mutex_lock lock(mtx_);
if (result_.has_value()) { default:
return result_.value(); return std::make_unique<rdb_file_db>(cfg);
} }
}
notify_.wait(lock); } // namespace repertory
return result_.value_or(api_error::error);
}
} // namespace repertory

View File

@ -1,43 +1,40 @@
/* /*
Copyright <2018-2024> <scott.e.graves@protonmail.com> Copyright <2018-2024> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include "file_manager/file_manager.hpp" #include "db/file_mgr_db.hpp"
namespace repertory { #include "app_config.hpp"
void file_manager::open_file_base::download::notify(const api_error &err) { #include "db/i_file_mgr_db.hpp"
complete_ = true; #include "db/impl/rdb_file_mgr_db.hpp"
error_ = err; #include "db/impl/sqlite_file_mgr_db.hpp"
unique_mutex_lock lock(mtx_);
notify_.notify_all(); namespace repertory {
} auto create_file_mgr_db(const app_config &cfg)
-> std::unique_ptr<i_file_mgr_db> {
auto file_manager::open_file_base::download::wait() -> api_error { switch (cfg.get_database_type()) {
if (not complete_) { case database_type::sqlite:
unique_mutex_lock lock(mtx_); return std::make_unique<sqlite_file_mgr_db>(cfg);
if (not complete_) {
notify_.wait(lock); default:
} return std::make_unique<rdb_file_mgr_db>(cfg);
notify_.notify_all(); }
} }
} // namespace repertory
return error_;
}
} // namespace repertory

View File

@ -0,0 +1,390 @@
/*
Copyright <2018-2024> <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.
*/
#include "db/impl/rdb_file_db.hpp"
#include "app_config.hpp"
#include "types/startup_exception.hpp"
#include "utils/config.hpp"
#include "utils/error_utils.hpp"
#include "utils/file.hpp"
#include "utils/path.hpp"
#include "utils/string.hpp"
#include "utils/utils.hpp"
namespace repertory {
rdb_file_db::rdb_file_db(const app_config &cfg) : cfg_(cfg) {
create_or_open(false);
}
rdb_file_db::~rdb_file_db() { db_.reset(); }
void rdb_file_db::create_or_open(bool clear) {
db_.reset();
auto families = std::vector<rocksdb::ColumnFamilyDescriptor>();
families.emplace_back(rocksdb::kDefaultColumnFamilyName,
rocksdb::ColumnFamilyOptions());
families.emplace_back("file", rocksdb::ColumnFamilyOptions());
families.emplace_back("path", rocksdb::ColumnFamilyOptions());
families.emplace_back("source", rocksdb::ColumnFamilyOptions());
auto handles = std::vector<rocksdb::ColumnFamilyHandle *>();
db_ = utils::create_rocksdb(cfg_, "file", families, handles, clear);
std::size_t idx{};
directory_family_ = handles.at(idx++);
file_family_ = handles.at(idx++);
path_family_ = handles.at(idx++);
source_family_ = handles.at(idx++);
}
auto rdb_file_db::add_directory(const std::string &api_path,
const std::string &source_path) -> api_error {
REPERTORY_USES_FUNCTION_NAME();
std::string existing_source_path;
auto result = get_directory_source_path(api_path, existing_source_path);
if (result != api_error::success &&
result != api_error::directory_not_found) {
return result;
}
return perform_action(
function_name, [&](rocksdb::Transaction *txn) -> rocksdb::Status {
if (not existing_source_path.empty()) {
auto res = remove_item(api_path, existing_source_path, txn);
if (not res.ok() && not res.IsNotFound()) {
return res;
}
}
auto res = txn->Put(directory_family_, api_path, source_path);
if (not res.ok()) {
return res;
}
res = txn->Put(path_family_, api_path, source_path);
if (not res.ok()) {
return res;
}
return txn->Put(source_family_, source_path, api_path);
});
}
auto rdb_file_db::add_or_update_file(const i_file_db::file_data &data)
-> api_error {
REPERTORY_USES_FUNCTION_NAME();
std::string existing_source_path;
auto result = get_file_source_path(data.api_path, existing_source_path);
if (result != api_error::success && result != api_error::item_not_found) {
return result;
}
return perform_action(
function_name, [&](rocksdb::Transaction *txn) -> rocksdb::Status {
if (not existing_source_path.empty()) {
auto res = remove_item(data.api_path, existing_source_path, txn);
if (not res.ok() && not res.IsNotFound()) {
return res;
}
}
json json_data = {
{"file_size", data.file_size},
{"iv", data.iv_list},
{"source_path", data.source_path},
};
auto res = txn->Put(file_family_, data.api_path, json_data.dump());
if (not res.ok()) {
return res;
}
res = txn->Put(path_family_, data.api_path, data.source_path);
if (not res.ok()) {
return res;
}
return txn->Put(source_family_, data.source_path, data.api_path);
});
}
void rdb_file_db::clear() { create_or_open(true); }
auto rdb_file_db::create_iterator(rocksdb::ColumnFamilyHandle *family) const
-> std::shared_ptr<rocksdb::Iterator> {
return std::shared_ptr<rocksdb::Iterator>(
db_->NewIterator(rocksdb::ReadOptions{}, family));
}
auto rdb_file_db::count() const -> std::uint64_t {
std::uint64_t ret{};
auto iter = create_iterator(source_family_);
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
++ret;
}
return ret;
}
auto rdb_file_db::get_api_path(const std::string &source_path,
std::string &api_path) const -> api_error {
REPERTORY_USES_FUNCTION_NAME();
return perform_action(function_name, [&]() -> rocksdb::Status {
return db_->Get(rocksdb::ReadOptions{}, source_family_, source_path,
&api_path);
});
}
auto rdb_file_db::get_directory_api_path(
const std::string &source_path, std::string &api_path) const -> api_error {
REPERTORY_USES_FUNCTION_NAME();
auto result = perform_action(function_name, [&]() -> rocksdb::Status {
auto res = db_->Get(rocksdb::ReadOptions{}, source_family_, source_path,
&api_path);
if (not res.ok()) {
return res;
}
std::string value;
return db_->Get(rocksdb::ReadOptions{}, directory_family_, api_path,
&value);
});
if (result != api_error::success) {
api_path.clear();
}
return result == api_error::item_not_found ? api_error::directory_not_found
: result;
}
auto rdb_file_db::get_directory_source_path(
const std::string &api_path, std::string &source_path) const -> api_error {
REPERTORY_USES_FUNCTION_NAME();
auto result = perform_action(function_name, [&]() -> rocksdb::Status {
return db_->Get(rocksdb::ReadOptions{}, directory_family_, api_path,
&source_path);
});
return result == api_error::item_not_found ? api_error::directory_not_found
: result;
}
auto rdb_file_db::get_file_api_path(const std::string &source_path,
std::string &api_path) const -> api_error {
REPERTORY_USES_FUNCTION_NAME();
auto result = perform_action(function_name, [&]() -> rocksdb::Status {
auto res = db_->Get(rocksdb::ReadOptions{}, source_family_, source_path,
&api_path);
if (not res.ok()) {
return res;
}
std::string value;
return db_->Get(rocksdb::ReadOptions{}, file_family_, api_path, &value);
});
if (result != api_error::success) {
api_path.clear();
}
return result;
}
auto rdb_file_db::get_file_data(const std::string &api_path,
i_file_db::file_data &data) const -> api_error {
REPERTORY_USES_FUNCTION_NAME();
auto result = perform_action(function_name, [&]() -> rocksdb::Status {
std::string value;
auto res = db_->Get(rocksdb::ReadOptions{}, file_family_, api_path, &value);
if (not res.ok()) {
return res;
}
auto json_data = json::parse(value);
data.api_path = api_path;
data.file_size = json_data.at("file_size").get<std::uint64_t>();
data.iv_list =
json_data.at("iv")
.get<std::vector<
std::array<unsigned char,
crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>>();
data.source_path = json_data.at("source_path").get<std::string>();
return res;
});
return result;
}
auto rdb_file_db::get_file_source_path(
const std::string &api_path, std::string &source_path) const -> api_error {
REPERTORY_USES_FUNCTION_NAME();
auto result = perform_action(function_name, [&]() -> rocksdb::Status {
std::string value;
auto res = db_->Get(rocksdb::ReadOptions{}, file_family_, api_path, &value);
if (not res.ok()) {
return res;
}
auto json_data = json::parse(value);
source_path = json_data.at("source_path").get<std::string>();
return res;
});
return result;
}
auto rdb_file_db::get_item_list() const -> std::vector<i_file_db::file_info> {
std::vector<i_file_db::file_info> ret{};
{
auto iter = create_iterator(directory_family_);
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
ret.emplace_back(i_file_db::file_info{
iter->key().ToString(),
true,
iter->value().ToString(),
});
}
}
{
auto iter = create_iterator(file_family_);
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
auto json_data = json::parse(iter->value().ToString());
ret.emplace_back(i_file_db::file_info{
iter->key().ToString(),
true,
json_data.at("source_path").get<std::string>(),
});
}
}
return ret;
}
auto rdb_file_db::get_source_path(const std::string &api_path,
std::string &source_path) const -> api_error {
REPERTORY_USES_FUNCTION_NAME();
return perform_action(function_name, [&]() -> rocksdb::Status {
return db_->Get(rocksdb::ReadOptions{}, path_family_, api_path,
&source_path);
});
}
auto rdb_file_db::perform_action(std::string_view function_name,
std::function<rocksdb::Status()> action)
-> api_error {
auto res = action();
if (res.ok()) {
return api_error::success;
}
if (not res.IsNotFound()) {
utils::error::raise_error(function_name, res.ToString());
}
return res.IsNotFound() ? api_error::item_not_found : api_error::error;
}
auto rdb_file_db::perform_action(
std::string_view function_name,
std::function<rocksdb::Status(rocksdb::Transaction *txn)> action)
-> api_error {
std::unique_ptr<rocksdb::Transaction> txn{
db_->BeginTransaction(rocksdb::WriteOptions{},
rocksdb::TransactionOptions{}),
};
try {
auto res = action(txn.get());
if (res.ok()) {
auto commit_res = txn->Commit();
if (commit_res.ok()) {
return api_error::success;
}
utils::error::raise_error(function_name,
"rocksdb commit failed|" + res.ToString());
return api_error::error;
}
utils::error::raise_error(function_name,
"rocksdb action failed|" + res.ToString());
} catch (const std::exception &ex) {
utils::error::raise_error(function_name, ex,
"failed to handle rocksdb action");
}
auto rollback_res = txn->Rollback();
utils::error::raise_error(function_name, "rocksdb rollback failed|" +
rollback_res.ToString());
return api_error::error;
}
auto rdb_file_db::remove_item(const std::string &api_path) -> api_error {
REPERTORY_USES_FUNCTION_NAME();
std::string source_path;
auto res = get_source_path(api_path, source_path);
if (res != api_error::success) {
return res;
}
return perform_action(function_name,
[&](rocksdb::Transaction *txn) -> rocksdb::Status {
return remove_item(api_path, source_path, txn);
});
}
auto rdb_file_db::remove_item(const std::string &api_path,
const std::string &source_path,
rocksdb::Transaction *txn) -> rocksdb::Status {
auto res = txn->Delete(source_family_, source_path);
if (not res.ok()) {
return res;
}
res = txn->Delete(path_family_, api_path);
if (not res.ok()) {
return res;
}
res = txn->Delete(directory_family_, api_path);
if (not res.ok()) {
return res;
}
return txn->Delete(file_family_, api_path);
}
} // namespace repertory

View File

@ -0,0 +1,327 @@
/*
Copyright <2018-2024> <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.
*/
#include "db/impl/rdb_file_mgr_db.hpp"
#include "app_config.hpp"
#include "types/startup_exception.hpp"
#include "utils/config.hpp"
#include "utils/error_utils.hpp"
#include "utils/file.hpp"
#include "utils/path.hpp"
#include "utils/string.hpp"
#include "utils/utils.hpp"
namespace repertory {
rdb_file_mgr_db::rdb_file_mgr_db(const app_config &cfg) : cfg_(cfg) {
create_or_open(false);
}
rdb_file_mgr_db::~rdb_file_mgr_db() { db_.reset(); }
void rdb_file_mgr_db::create_or_open(bool clear) {
db_.reset();
auto families = std::vector<rocksdb::ColumnFamilyDescriptor>();
families.emplace_back(rocksdb::kDefaultColumnFamilyName,
rocksdb::ColumnFamilyOptions());
families.emplace_back("upload_active", rocksdb::ColumnFamilyOptions());
families.emplace_back("upload", rocksdb::ColumnFamilyOptions());
auto handles = std::vector<rocksdb::ColumnFamilyHandle *>();
db_ = utils::create_rocksdb(cfg_, "file_mgr", families, handles, clear);
std::size_t idx{};
resume_family_ = handles.at(idx++);
upload_active_family_ = handles.at(idx++);
upload_family_ = handles.at(idx++);
}
auto rdb_file_mgr_db::add_resume(const resume_entry &entry) -> bool {
REPERTORY_USES_FUNCTION_NAME();
return perform_action(
function_name,
[this, &entry](rocksdb::Transaction *txn) -> rocksdb::Status {
return add_resume(entry, txn);
});
}
auto rdb_file_mgr_db::add_resume(const resume_entry &entry,
rocksdb::Transaction *txn) -> rocksdb::Status {
REPERTORY_USES_FUNCTION_NAME();
auto data = json({
{"chunk_size", entry.chunk_size},
{"read_state", utils::string::from_dynamic_bitset(entry.read_state)},
{"source_path", entry.source_path},
});
return txn->Put(resume_family_, entry.api_path, data.dump());
}
auto rdb_file_mgr_db::add_upload(const upload_entry &entry) -> bool {
REPERTORY_USES_FUNCTION_NAME();
return perform_action(
function_name,
[this, &entry](rocksdb::Transaction *txn) -> rocksdb::Status {
return txn->Put(upload_family_,
utils::string::zero_pad(std::to_string(++id_), 20U) +
'|' + entry.api_path,
entry.source_path);
});
}
auto rdb_file_mgr_db::add_upload_active(const upload_active_entry &entry)
-> bool {
REPERTORY_USES_FUNCTION_NAME();
return perform_action(
function_name,
[this, &entry](rocksdb::Transaction *txn) -> rocksdb::Status {
return txn->Put(upload_active_family_, entry.api_path,
entry.source_path);
});
}
void rdb_file_mgr_db::clear() { create_or_open(true); }
auto rdb_file_mgr_db::create_iterator(rocksdb::ColumnFamilyHandle *family) const
-> std::shared_ptr<rocksdb::Iterator> {
return std::shared_ptr<rocksdb::Iterator>(
db_->NewIterator(rocksdb::ReadOptions(), family));
}
auto rdb_file_mgr_db::get_next_upload() const -> std::optional<upload_entry> {
auto iter = create_iterator(upload_family_);
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
auto parts = utils::string::split(iter->key().ToString(), '|', false);
parts.erase(parts.begin());
auto api_path = utils::string::join(parts, '|');
return upload_entry{
api_path,
iter->value().ToString(),
};
}
return std::nullopt;
}
auto rdb_file_mgr_db::get_resume_list() const -> std::vector<resume_entry> {
std::vector<resume_entry> ret;
auto iter = create_iterator(resume_family_);
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
auto data = json::parse(iter->value().ToString());
ret.emplace_back(resume_entry{
iter->key().ToString(),
data.at("chunk_size").get<std::uint64_t>(),
utils::string::to_dynamic_bitset(
data.at("read_state").get<std::string>()),
data.at("source_path").get<std::string>(),
});
}
return ret;
}
auto rdb_file_mgr_db::get_upload(const std::string &api_path) const
-> std::optional<upload_entry> {
auto iter = create_iterator(upload_family_);
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
auto parts = utils::string::split(iter->key().ToString(), '|', false);
parts.erase(parts.begin());
if (api_path != utils::string::join(parts, '|')) {
continue;
}
return upload_entry{
api_path,
iter->value().ToString(),
};
}
return std::nullopt;
}
auto rdb_file_mgr_db::get_upload_active_list() const
-> std::vector<upload_active_entry> {
std::vector<upload_active_entry> ret;
auto iter = create_iterator(upload_active_family_);
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
ret.emplace_back(upload_active_entry{
iter->key().ToString(),
iter->value().ToString(),
});
}
return ret;
}
auto rdb_file_mgr_db::perform_action(std::string_view function_name,
std::function<rocksdb::Status()> action)
-> bool {
try {
auto res = action();
if (not res.ok()) {
utils::error::raise_error(function_name, res.ToString());
}
return res.ok();
} catch (const std::exception &ex) {
utils::error::raise_error(function_name, ex);
}
return false;
}
auto rdb_file_mgr_db::perform_action(
std::string_view function_name,
std::function<rocksdb::Status(rocksdb::Transaction *txn)> action) -> bool {
std::unique_ptr<rocksdb::Transaction> txn{
db_->BeginTransaction(rocksdb::WriteOptions{},
rocksdb::TransactionOptions{}),
};
try {
auto res = action(txn.get());
if (res.ok()) {
auto commit_res = txn->Commit();
if (commit_res.ok()) {
return true;
}
utils::error::raise_error(function_name,
"rocksdb commit failed|" + res.ToString());
return false;
}
utils::error::raise_error(function_name,
"rocksdb action failed|" + res.ToString());
} catch (const std::exception &ex) {
utils::error::raise_error(function_name, ex,
"failed to handle rocksdb action");
}
auto rollback_res = txn->Rollback();
utils::error::raise_error(function_name, "rocksdb rollback failed|" +
rollback_res.ToString());
return false;
}
auto rdb_file_mgr_db::remove_resume(const std::string &api_path) -> bool {
REPERTORY_USES_FUNCTION_NAME();
return perform_action(
function_name,
[this, &api_path](rocksdb::Transaction *txn) -> rocksdb::Status {
return remove_resume(api_path, txn);
});
}
auto rdb_file_mgr_db::remove_resume(
const std::string &api_path, rocksdb::Transaction *txn) -> rocksdb::Status {
return txn->Delete(resume_family_, api_path);
}
auto rdb_file_mgr_db::remove_upload(const std::string &api_path) -> bool {
REPERTORY_USES_FUNCTION_NAME();
auto iter = create_iterator(upload_family_);
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
auto parts = utils::string::split(iter->key().ToString(), '|', false);
parts.erase(parts.begin());
if (api_path != utils::string::join(parts, '|')) {
continue;
}
return perform_action(
function_name,
[this, &iter](rocksdb::Transaction *txn) -> rocksdb::Status {
return txn->Delete(upload_family_, iter->key());
});
}
return true;
}
auto rdb_file_mgr_db::remove_upload_active(const std::string &api_path)
-> bool {
REPERTORY_USES_FUNCTION_NAME();
return perform_action(
function_name,
[this, &api_path](rocksdb::Transaction *txn) -> rocksdb::Status {
return txn->Delete(upload_active_family_, api_path);
});
}
auto rdb_file_mgr_db::rename_resume(const std::string &from_api_path,
const std::string &to_api_path) -> bool {
REPERTORY_USES_FUNCTION_NAME();
bool not_found{false};
std::string value;
auto res = perform_action(
function_name,
[this, &from_api_path, &not_found, &value]() -> rocksdb::Status {
auto result = db_->Get(rocksdb::ReadOptions{}, from_api_path, &value);
not_found = result.IsNotFound();
return result;
});
if (not_found) {
return true;
}
if (not res) {
return false;
}
if (value.empty()) {
return true;
}
auto data = json::parse(value);
resume_entry entry{
to_api_path,
data.at("chunk_size").get<std::uint64_t>(),
utils::string::to_dynamic_bitset(
data.at("read_state").get<std::string>()),
data.at("source_path").get<std::string>(),
};
return perform_action(function_name,
[this, &entry, &from_api_path](
rocksdb::Transaction *txn) -> rocksdb::Status {
auto txn_res = remove_resume(from_api_path, txn);
if (not txn_res.ok()) {
return txn_res;
}
return add_resume(entry, txn);
});
}
} // namespace repertory

View File

@ -0,0 +1,511 @@
/*
Copyright <2018-2024> <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.
*/
#include "db/impl/rdb_meta_db.hpp"
#include "app_config.hpp"
#include "types/startup_exception.hpp"
#include "utils/error_utils.hpp"
#include "utils/file.hpp"
#include "utils/path.hpp"
#include "utils/string.hpp"
#include "utils/utils.hpp"
namespace repertory {
rdb_meta_db::rdb_meta_db(const app_config &cfg) : cfg_(cfg) {
create_or_open(false);
}
rdb_meta_db::~rdb_meta_db() { db_.reset(); }
void rdb_meta_db::create_or_open(bool clear) {
db_.reset();
auto families = std::vector<rocksdb::ColumnFamilyDescriptor>();
families.emplace_back(rocksdb::kDefaultColumnFamilyName,
rocksdb::ColumnFamilyOptions());
families.emplace_back("pinned", rocksdb::ColumnFamilyOptions());
families.emplace_back("size", rocksdb::ColumnFamilyOptions());
families.emplace_back("source", rocksdb::ColumnFamilyOptions());
auto handles = std::vector<rocksdb::ColumnFamilyHandle *>();
db_ = utils::create_rocksdb(cfg_, "provider_meta", families, handles, clear);
std::size_t idx{};
meta_family_ = handles.at(idx++);
pinned_family_ = handles.at(idx++);
size_family_ = handles.at(idx++);
source_family_ = handles.at(idx++);
}
void rdb_meta_db::clear() { create_or_open(true); }
auto rdb_meta_db::create_iterator(rocksdb::ColumnFamilyHandle *family) const
-> std::shared_ptr<rocksdb::Iterator> {
return std::shared_ptr<rocksdb::Iterator>(
db_->NewIterator(rocksdb::ReadOptions{}, family));
}
auto rdb_meta_db::get_api_path(const std::string &source_path,
std::string &api_path) const -> api_error {
REPERTORY_USES_FUNCTION_NAME();
if (source_path.empty()) {
return api_error::item_not_found;
}
return perform_action(function_name, [&]() -> rocksdb::Status {
return db_->Get(rocksdb::ReadOptions{}, source_family_, source_path,
&api_path);
});
}
auto rdb_meta_db::get_api_path_list() const -> std::vector<std::string> {
std::vector<std::string> ret;
auto iter = create_iterator(meta_family_);
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
ret.push_back(iter->key().ToString());
}
return ret;
}
auto rdb_meta_db::get_item_meta_json(const std::string &api_path,
json &json_data) const -> api_error {
REPERTORY_USES_FUNCTION_NAME();
try {
json_data.clear();
{
std::string value;
auto res = perform_action(function_name, [&]() -> rocksdb::Status {
return db_->Get(rocksdb::ReadOptions{}, meta_family_, api_path, &value);
});
if (res != api_error::success) {
return res;
}
if (not value.empty()) {
json_data = json::parse(value);
}
}
{
std::string value;
auto res = perform_action(function_name, [&]() -> rocksdb::Status {
return db_->Get(rocksdb::ReadOptions{}, pinned_family_, api_path,
&value);
});
if (res != api_error::success) {
return res;
}
if (not value.empty()) {
json_data[META_PINNED] = value;
}
}
{
std::string value;
auto res = perform_action(function_name, [&]() -> rocksdb::Status {
return db_->Get(rocksdb::ReadOptions{}, size_family_, api_path, &value);
});
if (res != api_error::success) {
return res;
}
if (not value.empty()) {
json_data[META_SIZE] = value;
}
}
return json_data.empty() ? api_error::item_not_found : api_error::success;
} catch (const std::exception &e) {
utils::error::raise_api_path_error(function_name, api_path, e,
"failed to get item meta");
}
return api_error::error;
}
auto rdb_meta_db::get_item_meta(const std::string &api_path,
api_meta_map &meta) const -> api_error {
json json_data;
auto ret = get_item_meta_json(api_path, json_data);
if (ret != api_error::success) {
return ret;
}
for (auto it = json_data.begin(); it != json_data.end(); ++it) {
meta[it.key()] = it.value().get<std::string>();
}
return api_error::success;
}
auto rdb_meta_db::get_item_meta(const std::string &api_path,
const std::string &key,
std::string &value) const -> api_error {
REPERTORY_USES_FUNCTION_NAME();
if (key == META_PINNED) {
return perform_action(function_name, [&]() -> rocksdb::Status {
return db_->Get(rocksdb::ReadOptions{}, pinned_family_, api_path, &value);
});
}
if (key == META_SIZE) {
return perform_action(function_name, [&]() -> rocksdb::Status {
return db_->Get(rocksdb::ReadOptions{}, size_family_, api_path, &value);
});
}
json json_data;
auto ret = get_item_meta_json(api_path, json_data);
if (ret != api_error::success) {
return ret;
}
if (json_data.find(key) != json_data.end()) {
value = json_data[key].get<std::string>();
}
return api_error::success;
}
auto rdb_meta_db::get_pinned_files() const -> std::vector<std::string> {
std::vector<std::string> ret;
auto iter = create_iterator(pinned_family_);
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
if (not utils::string::to_bool(iter->value().ToString())) {
continue;
}
ret.push_back(iter->key().ToString());
}
return ret;
}
auto rdb_meta_db::get_total_item_count() const -> std::uint64_t {
std::uint64_t ret{};
auto iter = create_iterator(meta_family_);
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
++ret;
}
return ret;
}
auto rdb_meta_db::get_total_size() const -> std::uint64_t {
std::uint64_t ret{};
auto iter = create_iterator(size_family_);
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
ret += utils::string::to_uint64(iter->value().ToString());
}
return ret;
}
auto rdb_meta_db::perform_action(std::string_view function_name,
std::function<rocksdb::Status()> action)
-> api_error {
auto res = action();
if (res.ok()) {
return api_error::success;
}
if (not res.IsNotFound()) {
utils::error::raise_error(function_name, res.ToString());
}
return res.IsNotFound() ? api_error::item_not_found : api_error::error;
}
auto rdb_meta_db::perform_action(
std::string_view function_name,
std::function<rocksdb::Status(rocksdb::Transaction *txn)> action)
-> api_error {
std::unique_ptr<rocksdb::Transaction> txn{
db_->BeginTransaction(rocksdb::WriteOptions{},
rocksdb::TransactionOptions{}),
};
try {
auto res = action(txn.get());
if (res.ok()) {
auto commit_res = txn->Commit();
if (commit_res.ok()) {
return api_error::success;
}
utils::error::raise_error(function_name,
"rocksdb commit failed|" + res.ToString());
return api_error::error;
}
utils::error::raise_error(function_name,
"rocksdb action failed|" + res.ToString());
} catch (const std::exception &ex) {
utils::error::raise_error(function_name, ex,
"failed to handle rocksdb action");
}
auto rollback_res = txn->Rollback();
utils::error::raise_error(function_name, "rocksdb rollback failed|" +
rollback_res.ToString());
return api_error::error;
}
void rdb_meta_db::remove_api_path(const std::string &api_path) {
REPERTORY_USES_FUNCTION_NAME();
std::string source_path;
auto res = get_item_meta(api_path, META_SOURCE, source_path);
if (res != api_error::success) {
utils::error::raise_api_path_error(function_name, api_path, res,
"failed to get source path");
}
res = perform_action(function_name,
[this, &api_path, &source_path](
rocksdb::Transaction *txn) -> rocksdb::Status {
return remove_api_path(api_path, source_path, txn);
});
if (res != api_error::success) {
utils::error::raise_api_path_error(function_name, api_path, res,
"failed to remove api path");
}
}
auto rdb_meta_db::remove_api_path(const std::string &api_path,
const std::string &source_path,
rocksdb::Transaction *txn)
-> rocksdb::Status {
auto txn_res = txn->Delete(pinned_family_, api_path);
if (not txn_res.ok()) {
return txn_res;
}
txn_res = txn->Delete(size_family_, api_path);
if (not txn_res.ok()) {
return txn_res;
}
if (not source_path.empty()) {
txn_res = txn->Delete(source_family_, source_path);
if (not txn_res.ok()) {
return txn_res;
}
}
return txn->Delete(meta_family_, api_path);
}
auto rdb_meta_db::remove_item_meta(const std::string &api_path,
const std::string &key) -> api_error {
if (key == META_DIRECTORY || key == META_PINNED || key == META_SIZE ||
key == META_SOURCE) {
// TODO log warning for unsupported attributes
return api_error::success;
}
json json_data;
auto res = get_item_meta_json(api_path, json_data);
if (res != api_error::success) {
return res;
}
json_data.erase(key);
return update_item_meta(api_path, json_data);
}
auto rdb_meta_db::rename_item_meta(const std::string &from_api_path,
const std::string &to_api_path)
-> api_error {
REPERTORY_USES_FUNCTION_NAME();
json json_data;
auto res = get_item_meta_json(from_api_path, json_data);
if (res != api_error::success) {
return res;
}
return perform_action(
function_name, [&](rocksdb::Transaction *txn) -> rocksdb::Status {
auto txn_res = remove_api_path(
from_api_path, json_data[META_SOURCE].get<std::string>(), txn);
if (not txn_res.ok()) {
return txn_res;
}
rocksdb::Status status;
[[maybe_unused]] auto api_res =
update_item_meta(to_api_path, json_data, txn, &status);
return status;
});
}
auto rdb_meta_db::set_item_meta(const std::string &api_path,
const std::string &key,
const std::string &value) -> api_error {
REPERTORY_USES_FUNCTION_NAME();
if (key == META_PINNED) {
return perform_action(function_name,
[&](rocksdb::Transaction *txn) -> rocksdb::Status {
return txn->Put(pinned_family_, api_path, value);
});
}
if (key == META_SIZE) {
return perform_action(function_name,
[&](rocksdb::Transaction *txn) -> rocksdb::Status {
return txn->Put(size_family_, api_path, value);
});
}
json json_data;
auto res = get_item_meta_json(api_path, json_data);
if (res != api_error::success && res != api_error::item_not_found) {
return res;
}
json_data[key] = value;
return update_item_meta(api_path, json_data);
}
auto rdb_meta_db::set_item_meta(const std::string &api_path,
const api_meta_map &meta) -> api_error {
json json_data;
auto res = get_item_meta_json(api_path, json_data);
if (res != api_error::success && res != api_error::item_not_found) {
return res;
}
for (const auto &data : meta) {
json_data[data.first] = data.second;
}
return update_item_meta(api_path, json_data);
}
auto rdb_meta_db::update_item_meta(const std::string &api_path, json json_data,
rocksdb::Transaction *base_txn,
rocksdb::Status *status) -> api_error {
REPERTORY_USES_FUNCTION_NAME();
try {
if (not json_data.contains(META_PINNED)) {
json_data[META_PINNED] = utils::string::from_bool(false);
}
if (not json_data.contains(META_SIZE)) {
json_data[META_SIZE] = "0";
}
if (not json_data.contains(META_SOURCE)) {
json_data[META_SOURCE] = "";
}
auto directory =
utils::string::to_bool(json_data.at(META_DIRECTORY).get<std::string>());
auto pinned = directory ? false
: utils::string::to_bool(
json_data.at(META_PINNED).get<std::string>());
auto size = directory ? std::uint64_t(0U)
: utils::string::to_uint64(
json_data.at(META_SIZE).get<std::string>());
auto source_path = directory ? std::string("")
: json_data.at(META_SOURCE).get<std::string>();
json_data[META_PINNED] = utils::string::from_bool(pinned);
json_data[META_SIZE] = std::to_string(size);
json_data[META_SOURCE] = source_path;
auto should_del_source{false};
std::string orig_source_path;
if (not directory) {
auto res = get_item_meta(api_path, META_SOURCE, orig_source_path);
if (res != api_error::success && res != api_error::item_not_found) {
return res;
}
should_del_source =
not orig_source_path.empty() && orig_source_path != source_path;
}
json_data.erase(META_PINNED);
json_data.erase(META_SIZE);
const auto set_status = [&status](rocksdb::Status res) -> rocksdb::Status {
if (status != nullptr) {
*status = res;
}
return res;
};
const auto do_transaction =
[&](rocksdb::Transaction *txn) -> rocksdb::Status {
if (should_del_source) {
auto res = set_status(txn->Delete(source_family_, orig_source_path));
if (not res.ok()) {
return res;
}
}
auto res = set_status(
txn->Put(pinned_family_, api_path, utils::string::from_bool(pinned)));
if (not res.ok()) {
return res;
}
res = set_status(txn->Put(size_family_, api_path, std::to_string(size)));
if (not res.ok()) {
return res;
}
if (not source_path.empty()) {
res = set_status(txn->Put(source_family_, source_path, api_path));
if (not res.ok()) {
return res;
}
}
return set_status(txn->Put(meta_family_, api_path, json_data.dump()));
};
if (base_txn == nullptr) {
return perform_action(function_name, do_transaction);
}
auto res = set_status(do_transaction(base_txn));
if (res.ok()) {
return api_error::success;
}
} catch (const std::exception &e) {
utils::error::raise_api_path_error(function_name, api_path, e,
"failed to update item meta");
}
return api_error::error;
}
} // namespace repertory

View File

@ -0,0 +1,334 @@
/*
Copyright <2018-2024> <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.
*/
#include "db/impl/sqlite_file_db.hpp"
#include "app_config.hpp"
#include "types/startup_exception.hpp"
#include "utils/config.hpp"
#include "utils/db/sqlite/db_common.hpp"
#include "utils/db/sqlite/db_delete.hpp"
#include "utils/db/sqlite/db_insert.hpp"
#include "utils/db/sqlite/db_select.hpp"
#include "utils/db/sqlite/db_update.hpp"
#include "utils/error_utils.hpp"
#include "utils/file.hpp"
#include "utils/path.hpp"
#include "utils/string.hpp"
namespace {
const std::string file_table = "file";
const std::map<std::string, std::string> sql_create_tables = {
{
{file_table},
{"CREATE TABLE IF NOT EXISTS " + file_table +
"("
"source_path TEXT PRIMARY KEY ASC, "
"api_path TEXT UNIQUE NOT NULL, "
"iv TEXT DEFAULT '' NOT NULL, "
"directory INTEGER NOT NULL, "
"size INTEGER DEFAULT 0 NOT NULL"
");"},
},
};
} // namespace
namespace repertory {
sqlite_file_db::sqlite_file_db(const app_config &cfg) {
auto db_dir = utils::path::combine(cfg.get_data_directory(), {"db"});
if (not utils::file::directory{db_dir}.create_directory()) {
throw startup_exception(
fmt::format("failed to create db directory|", db_dir));
}
db_ = utils::db::sqlite::create_db(utils::path::combine(db_dir, {"file.db"}),
sql_create_tables);
}
sqlite_file_db::~sqlite_file_db() { db_.reset(); }
auto sqlite_file_db::add_directory(const std::string &api_path,
const std::string &source_path)
-> api_error {
REPERTORY_USES_FUNCTION_NAME();
auto result = utils::db::sqlite::db_insert{*db_, file_table}
.column_value("api_path", api_path)
.column_value("directory", 1)
.column_value("source_path", source_path)
.go();
if (result.ok()) {
return api_error::success;
}
utils::error::raise_api_path_error(
function_name, api_path, api_error::error,
fmt::format("failed to add directory|{}", result.get_error_str()));
return api_error::error;
}
auto sqlite_file_db::add_or_update_file(const i_file_db::file_data &data)
-> api_error {
REPERTORY_USES_FUNCTION_NAME();
auto result =
utils::db::sqlite::db_insert{*db_, file_table}
.or_replace()
.column_value("api_path", data.api_path)
.column_value("directory", 0)
.column_value("iv", json(data.iv_list).dump())
.column_value("size", static_cast<std::int64_t>(data.file_size))
.column_value("source_path", data.source_path)
.go();
if (result.ok()) {
return api_error::success;
}
utils::error::raise_api_path_error(
function_name, data.api_path, api_error::error,
fmt::format("failed to add file|{}", result.get_error_str()));
return api_error::error;
}
void sqlite_file_db::clear() {
REPERTORY_USES_FUNCTION_NAME();
auto result = utils::db::sqlite::db_delete{*db_, file_table}.go();
if (not result.ok()) {
utils::error::raise_error(function_name,
fmt::format("failed to clear file table|{}",
std::to_string(result.get_error())));
}
}
auto sqlite_file_db::count() const -> std::uint64_t {
auto result = utils::db::sqlite::db_select{*db_, file_table}
.count("api_path", "count")
.go();
std::optional<utils::db::sqlite::db_result::row> row;
if (result.get_row(row) && row.has_value()) {
return static_cast<std::uint64_t>(
row->get_column("count").get_value<std::int64_t>());
}
return 0U;
}
auto sqlite_file_db::get_api_path(const std::string &source_path,
std::string &api_path) const -> api_error {
auto result = utils::db::sqlite::db_select{*db_, file_table}
.column("api_path")
.where("source_path")
.equals(source_path)
.op()
.limit(1)
.go();
std::optional<utils::db::sqlite::db_result::row> row;
if (result.get_row(row) && row.has_value()) {
api_path = row->get_column("api_path").get_value<std::string>();
return api_error::success;
}
return api_error::item_not_found;
}
auto sqlite_file_db::get_directory_api_path(const std::string &source_path,
std::string &api_path) const
-> api_error {
auto result = utils::db::sqlite::db_select{*db_, file_table}
.column("api_path")
.where("source_path")
.equals(source_path)
.and_()
.where("directory")
.equals(1)
.op()
.limit(1)
.go();
std::optional<utils::db::sqlite::db_result::row> row;
if (result.get_row(row) && row.has_value()) {
api_path = row->get_column("api_path").get_value<std::string>();
return api_error::success;
}
return api_error::directory_not_found;
}
auto sqlite_file_db::get_directory_source_path(const std::string &api_path,
std::string &source_path) const
-> api_error {
auto result = utils::db::sqlite::db_select{*db_, file_table}
.column("source_path")
.where("api_path")
.equals(api_path)
.and_()
.where("directory")
.equals(1)
.op()
.limit(1)
.go();
std::optional<utils::db::sqlite::db_result::row> row;
if (result.get_row(row) && row.has_value()) {
source_path = row->get_column("source_path").get_value<std::string>();
return api_error::success;
}
return api_error::directory_not_found;
}
auto sqlite_file_db::get_file_api_path(const std::string &source_path,
std::string &api_path) const
-> api_error {
auto result = utils::db::sqlite::db_select{*db_, file_table}
.column("api_path")
.where("source_path")
.equals(source_path)
.and_()
.where("directory")
.equals(0)
.op()
.limit(1)
.go();
std::optional<utils::db::sqlite::db_result::row> row;
if (result.get_row(row) && row.has_value()) {
api_path = row->get_column("api_path").get_value<std::string>();
return api_error::success;
}
return api_error::item_not_found;
}
auto sqlite_file_db::get_file_data(const std::string &api_path,
i_file_db::file_data &data) const
-> api_error {
auto result = utils::db::sqlite::db_select{*db_, file_table}
.column("iv")
.column("size")
.column("source_path")
.where("api_path")
.equals(api_path)
.and_()
.where("directory")
.equals(0)
.op()
.limit(1)
.go();
std::optional<utils::db::sqlite::db_result::row> row;
if (result.get_row(row) && row.has_value()) {
data.api_path = api_path;
data.file_size = static_cast<std::uint64_t>(
row->get_column("size").get_value<std::int64_t>());
data.source_path = row->get_column("source_path").get_value<std::string>();
auto str_data = row->get_column("iv").get_value<std::string>();
if (not str_data.empty()) {
data.iv_list =
json::parse(str_data)
.get<std::vector<
std::array<unsigned char,
crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>>();
}
return api_error::success;
}
return api_error::item_not_found;
}
auto sqlite_file_db::get_file_source_path(const std::string &api_path,
std::string &source_path) const
-> api_error {
auto result = utils::db::sqlite::db_select{*db_, file_table}
.column("source_path")
.where("api_path")
.equals(api_path)
.and_()
.where("directory")
.equals(0)
.op()
.limit(1)
.go();
std::optional<utils::db::sqlite::db_result::row> row;
if (result.get_row(row) && row.has_value()) {
source_path = row->get_column("source_path").get_value<std::string>();
return api_error::success;
}
return api_error::item_not_found;
}
auto sqlite_file_db::get_item_list() const
-> std::vector<i_file_db::file_info> {
std::vector<i_file_db::file_info> ret;
auto result = utils::db::sqlite::db_select{*db_, file_table}.go();
while (result.has_row()) {
std::optional<utils::db::sqlite::db_result::row> row;
if (result.get_row(row) && row.has_value()) {
ret.emplace_back(i_file_db::file_info{
row->get_column("api_path").get_value<std::string>(),
row->get_column("directory").get_value<std::int64_t>() == 1,
row->get_column("source_path").get_value<std::string>(),
});
}
result.next_row();
}
return ret;
}
auto sqlite_file_db::get_source_path(const std::string &api_path,
std::string &source_path) const
-> api_error {
auto result = utils::db::sqlite::db_select{*db_, file_table}
.column("source_path")
.where("api_path")
.equals(api_path)
.op()
.limit(1)
.go();
std::optional<utils::db::sqlite::db_result::row> row;
if (result.get_row(row) && row.has_value()) {
source_path = row->get_column("source_path").get_value<std::string>();
return api_error::success;
}
return api_error::item_not_found;
}
auto sqlite_file_db::remove_item(const std::string &api_path) -> api_error {
auto result = utils::db::sqlite::db_delete{*db_, file_table}
.where("api_path")
.equals(api_path)
.go();
return result.ok() ? api_error::success : api_error::error;
}
} // namespace repertory

View File

@ -0,0 +1,275 @@
/*
Copyright <2018-2024> <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.
*/
#include "db/impl/sqlite_file_mgr_db.hpp"
#include "app_config.hpp"
#include "types/startup_exception.hpp"
#include "utils/config.hpp"
#include "utils/db/sqlite/db_common.hpp"
#include "utils/db/sqlite/db_delete.hpp"
#include "utils/db/sqlite/db_insert.hpp"
#include "utils/db/sqlite/db_select.hpp"
#include "utils/db/sqlite/db_update.hpp"
#include "utils/error_utils.hpp"
#include "utils/file.hpp"
#include "utils/path.hpp"
#include "utils/string.hpp"
namespace {
const std::string resume_table = "resume";
const std::string upload_table = "upload";
const std::string upload_active_table = "upload_active";
const std::map<std::string, std::string> sql_create_tables{
{
{resume_table},
{
"CREATE TABLE IF NOT EXISTS " + resume_table +
"("
"api_path TEXT PRIMARY KEY ASC, "
"chunk_size INTEGER, "
"read_state TEXT, "
"source_path TEXT"
");",
},
},
{
{upload_table},
{
"CREATE TABLE IF NOT EXISTS " + upload_table +
"("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"api_path TEXT UNIQUE, "
"source_path TEXT"
");",
},
},
{
{upload_active_table},
{
"CREATE TABLE IF NOT EXISTS " + upload_active_table +
"("
"api_path TEXT PRIMARY KEY ASC, "
"source_path TEXT"
");",
},
},
};
} // namespace
namespace repertory {
sqlite_file_mgr_db::sqlite_file_mgr_db(const app_config &cfg) {
auto db_dir = utils::path::combine(cfg.get_data_directory(), {"db"});
if (not utils::file::directory{db_dir}.create_directory()) {
throw startup_exception(
fmt::format("failed to create db directory|", db_dir));
}
db_ = utils::db::sqlite::create_db(
utils::path::combine(db_dir, {"file_mgr.db"}), sql_create_tables);
}
sqlite_file_mgr_db::~sqlite_file_mgr_db() { db_.reset(); }
auto sqlite_file_mgr_db::add_resume(const resume_entry &entry) -> bool {
return utils::db::sqlite::db_insert{*db_, resume_table}
.or_replace()
.column_value("api_path", entry.api_path)
.column_value("chunk_size", static_cast<std::int64_t>(entry.chunk_size))
.column_value("read_state",
utils::string::from_dynamic_bitset(entry.read_state))
.column_value("source_path", entry.source_path)
.go()
.ok();
}
auto sqlite_file_mgr_db::add_upload(const upload_entry &entry) -> bool {
return utils::db::sqlite::db_insert{*db_, upload_table}
.or_replace()
.column_value("api_path", entry.api_path)
.column_value("source_path", entry.source_path)
.go()
.ok();
}
auto sqlite_file_mgr_db::add_upload_active(const upload_active_entry &entry)
-> bool {
return utils::db::sqlite::db_insert{*db_, upload_active_table}
.or_replace()
.column_value("api_path", entry.api_path)
.column_value("source_path", entry.source_path)
.go()
.ok();
}
void sqlite_file_mgr_db::clear() {
REPERTORY_USES_FUNCTION_NAME();
auto result = utils::db::sqlite::db_delete{*db_, resume_table}.go();
if (not result.ok()) {
utils::error::raise_error(function_name,
"failed to clear resume table|" +
std::to_string(result.get_error()));
}
result = utils::db::sqlite::db_delete{*db_, upload_active_table}.go();
if (not result.ok()) {
utils::error::raise_error(function_name,
"failed to clear upload active table|" +
std::to_string(result.get_error()));
}
result = utils::db::sqlite::db_delete{*db_, upload_table}.go();
if (not result.ok()) {
utils::error::raise_error(function_name,
"failed to clear upload table|" +
std::to_string(result.get_error()));
}
}
auto sqlite_file_mgr_db::get_next_upload() const
-> std::optional<upload_entry> {
auto result = utils::db::sqlite::db_select{*db_, upload_table}
.order_by("id", true)
.limit(1)
.go();
std::optional<utils::db::sqlite::db_result::row> row;
if (not result.get_row(row) || not row.has_value()) {
return std::nullopt;
}
return upload_entry{
row->get_column("api_path").get_value<std::string>(),
row->get_column("source_path").get_value<std::string>(),
};
}
auto sqlite_file_mgr_db::get_resume_list() const -> std::vector<resume_entry> {
REPERTORY_USES_FUNCTION_NAME();
std::vector<resume_entry> ret;
auto result = utils::db::sqlite::db_select{*db_, resume_table}.go();
while (result.has_row()) {
try {
std::optional<utils::db::sqlite::db_result::row> row;
if (not result.get_row(row)) {
continue;
}
if (not row.has_value()) {
continue;
}
ret.push_back(resume_entry{
row->get_column("api_path").get_value<std::string>(),
static_cast<std::uint64_t>(
row->get_column("chunk_size").get_value<std::int64_t>()),
utils::string::to_dynamic_bitset(
row->get_column("read_state").get_value<std::string>()),
row->get_column("source_path").get_value<std::string>(),
});
} catch (const std::exception &ex) {
utils::error::raise_error(function_name, ex, "query error");
}
}
return ret;
}
auto sqlite_file_mgr_db::get_upload(const std::string &api_path) const
-> std::optional<upload_entry> {
auto result = utils::db::sqlite::db_select{*db_, upload_table}
.where("api_path")
.equals(api_path)
.go();
std::optional<utils::db::sqlite::db_result::row> row;
if (not result.get_row(row) || not row.has_value()) {
return std::nullopt;
}
return upload_entry{
row->get_column("api_path").get_value<std::string>(),
row->get_column("source_path").get_value<std::string>(),
};
}
auto sqlite_file_mgr_db::get_upload_active_list() const
-> std::vector<upload_active_entry> {
REPERTORY_USES_FUNCTION_NAME();
std::vector<upload_active_entry> ret;
auto result = utils::db::sqlite::db_select{*db_, upload_active_table}.go();
while (result.has_row()) {
try {
std::optional<utils::db::sqlite::db_result::row> row;
if (not result.get_row(row)) {
continue;
}
if (not row.has_value()) {
continue;
}
ret.push_back(upload_active_entry{
row->get_column("api_path").get_value<std::string>(),
row->get_column("source_path").get_value<std::string>(),
});
} catch (const std::exception &ex) {
utils::error::raise_error(function_name, ex, "query error");
}
}
return ret;
}
auto sqlite_file_mgr_db::remove_resume(const std::string &api_path) -> bool {
return utils::db::sqlite::db_delete{*db_, resume_table}
.where("api_path")
.equals(api_path)
.go()
.ok();
}
auto sqlite_file_mgr_db::remove_upload(const std::string &api_path) -> bool {
return utils::db::sqlite::db_delete{*db_, upload_table}
.where("api_path")
.equals(api_path)
.go()
.ok();
}
auto sqlite_file_mgr_db::remove_upload_active(const std::string &api_path)
-> bool {
return utils::db::sqlite::db_delete{*db_, upload_active_table}
.where("api_path")
.equals(api_path)
.go()
.ok();
}
auto sqlite_file_mgr_db::rename_resume(const std::string &from_api_path,
const std::string &to_api_path) -> bool {
return utils::db::sqlite::db_update{*db_, resume_table}
.column_value("api_path", to_api_path)
.where("api_path")
.equals(from_api_path)
.go()
.ok();
}
} // namespace repertory

View File

@ -19,69 +19,73 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include "providers/meta_db.hpp" #include "db/impl/sqlite_meta_db.hpp"
#include "app_config.hpp" #include "app_config.hpp"
#include "types/startup_exception.hpp"
#include "utils/db/sqlite/db_common.hpp" #include "utils/db/sqlite/db_common.hpp"
#include "utils/db/sqlite/db_delete.hpp" #include "utils/db/sqlite/db_delete.hpp"
#include "utils/db/sqlite/db_insert.hpp" #include "utils/db/sqlite/db_insert.hpp"
#include "utils/db/sqlite/db_select.hpp" #include "utils/db/sqlite/db_select.hpp"
#include "utils/error_utils.hpp" #include "utils/error_utils.hpp"
#include "utils/file.hpp"
#include "utils/path.hpp" #include "utils/path.hpp"
#include "utils/string.hpp" #include "utils/string.hpp"
namespace repertory { namespace repertory {
meta_db::meta_db(const app_config &cfg) { sqlite_meta_db::sqlite_meta_db(const app_config &cfg) {
static constexpr const std::string_view function_name{ const std::map<std::string, std::string> sql_create_tables{
static_cast<const char *>(__FUNCTION__), {
{"meta"},
{"CREATE TABLE IF NOT EXISTS "
"meta "
"("
"api_path TEXT PRIMARY KEY ASC, "
"data TEXT, "
"directory INTEGER, "
"pinned INTEGER, "
"size INTEGER, "
"source_path TEXT"
");"},
},
}; };
auto db_path = utils::path::combine(cfg.get_data_directory(), {"meta.db3"}); auto db_dir = utils::path::combine(cfg.get_data_directory(), {"db"});
if (not utils::file::directory{db_dir}.create_directory()) {
sqlite3 *db3{nullptr}; throw startup_exception(
auto res = fmt::format("failed to create db directory|", db_dir));
sqlite3_open_v2(db_path.c_str(), &db3,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr);
if (res != SQLITE_OK) {
utils::error::raise_error(function_name, "failed to open db|" + db_path +
'|' + std::to_string(res) +
'|' + sqlite3_errstr(res));
return;
}
db_.reset(db3);
const auto *create = "CREATE TABLE IF NOT EXISTS "
"meta "
"("
"api_path TEXT PRIMARY KEY ASC, "
"data TEXT, "
"directory INTEGER, "
"pinned INTEGER, "
"source_path TEXT"
");";
std::string err;
if (not utils::db::sqlite::execute_sql(*db_, create, err)) {
utils::error::raise_error(function_name,
"failed to create db|" + db_path + '|' + err);
db_.reset();
return;
} }
utils::db::sqlite::set_journal_mode(*db_); db_ = utils::db::sqlite::create_db(utils::path::combine(db_dir, {"meta.db"}),
sql_create_tables);
} }
meta_db::~meta_db() { db_.reset(); } sqlite_meta_db::~sqlite_meta_db() { db_.reset(); }
auto meta_db::get_api_path(const std::string &source_path, void sqlite_meta_db::clear() {
std::string &api_path) -> api_error { REPERTORY_USES_FUNCTION_NAME();
auto result = utils::db::sqlite::db_delete{*db_, table_name}.go();
if (result.ok()) {
return;
}
utils::error::raise_error(function_name,
"failed to clear meta db|" +
std::to_string(result.get_error()));
}
auto sqlite_meta_db::get_api_path(const std::string &source_path,
std::string &api_path) const -> api_error {
auto result = utils::db::sqlite::db_select{*db_, table_name} auto result = utils::db::sqlite::db_select{*db_, table_name}
.column("api_path") .column("api_path")
.where("source_path") .where("source_path")
.equals(source_path) .equals(source_path)
.op()
.limit(1) .limit(1)
.go(); .go();
std::optional<utils::db::sqlite::db_select::row> row; std::optional<utils::db::sqlite::db_result::row> row;
if (result.get_row(row) && row.has_value()) { if (result.get_row(row) && row.has_value()) {
api_path = row->get_column("api_path").get_value<std::string>(); api_path = row->get_column("api_path").get_value<std::string>();
return api_error::success; return api_error::success;
@ -90,13 +94,13 @@ auto meta_db::get_api_path(const std::string &source_path,
return api_error::item_not_found; return api_error::item_not_found;
} }
auto meta_db::get_api_path_list() -> std::vector<std::string> { auto sqlite_meta_db::get_api_path_list() const -> std::vector<std::string> {
std::vector<std::string> ret{}; std::vector<std::string> ret{};
auto result = auto result =
utils::db::sqlite::db_select{*db_, table_name}.column("api_path").go(); utils::db::sqlite::db_select{*db_, table_name}.column("api_path").go();
while (result.has_row()) { while (result.has_row()) {
std::optional<utils::db::sqlite::db_select::row> row; std::optional<utils::db::sqlite::db_result::row> row;
if (result.get_row(row) && row.has_value()) { if (result.get_row(row) && row.has_value()) {
ret.push_back(row->get_column("api_path").get_value<std::string>()); ret.push_back(row->get_column("api_path").get_value<std::string>());
} }
@ -105,16 +109,15 @@ auto meta_db::get_api_path_list() -> std::vector<std::string> {
return ret; return ret;
} }
auto meta_db::get_item_meta(const std::string &api_path, auto sqlite_meta_db::get_item_meta(const std::string &api_path,
api_meta_map &meta) -> api_error { api_meta_map &meta) const -> api_error {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
auto result = utils::db::sqlite::db_select{*db_, table_name} auto result = utils::db::sqlite::db_select{*db_, table_name}
.column("*") .column("*")
.where("api_path") .where("api_path")
.equals(api_path) .equals(api_path)
.op()
.limit(1) .limit(1)
.go(); .go();
if (not result.has_row()) { if (not result.has_row()) {
@ -122,7 +125,7 @@ auto meta_db::get_item_meta(const std::string &api_path,
} }
try { try {
std::optional<utils::db::sqlite::db_select::row> row; std::optional<utils::db::sqlite::db_result::row> row;
if (result.get_row(row) && row.has_value()) { if (result.get_row(row) && row.has_value()) {
meta = json::parse(row->get_column("data").get_value<std::string>()) meta = json::parse(row->get_column("data").get_value<std::string>())
.get<api_meta_map>(); .get<api_meta_map>();
@ -130,9 +133,10 @@ auto meta_db::get_item_meta(const std::string &api_path,
row->get_column("directory").get_value<std::int64_t>() == 1); row->get_column("directory").get_value<std::int64_t>() == 1);
meta[META_PINNED] = utils::string::from_bool( meta[META_PINNED] = utils::string::from_bool(
row->get_column("pinned").get_value<std::int64_t>() == 1); row->get_column("pinned").get_value<std::int64_t>() == 1);
meta[META_SIZE] = std::to_string(static_cast<std::uint64_t>(
row->get_column("size").get_value<std::int64_t>()));
meta[META_SOURCE] = meta[META_SOURCE] =
row->get_column("source_path").get_value<std::string>(); row->get_column("source_path").get_value<std::string>();
return api_error::success; return api_error::success;
} }
@ -145,16 +149,16 @@ auto meta_db::get_item_meta(const std::string &api_path,
return api_error::error; return api_error::error;
} }
auto meta_db::get_item_meta(const std::string &api_path, const std::string &key, auto sqlite_meta_db::get_item_meta(const std::string &api_path,
std::string &value) const -> api_error { const std::string &key,
static constexpr const std::string_view function_name{ std::string &value) const -> api_error {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
auto result = utils::db::sqlite::db_select{*db_, table_name} auto result = utils::db::sqlite::db_select{*db_, table_name}
.column("*") .column("*")
.where("api_path") .where("api_path")
.equals(api_path) .equals(api_path)
.op()
.limit(1) .limit(1)
.go(); .go();
if (not result.has_row()) { if (not result.has_row()) {
@ -162,7 +166,7 @@ auto meta_db::get_item_meta(const std::string &api_path, const std::string &key,
} }
try { try {
std::optional<utils::db::sqlite::db_select::row> row; std::optional<utils::db::sqlite::db_result::row> row;
if (result.get_row(row) && row.has_value()) { if (result.get_row(row) && row.has_value()) {
value = value =
key == META_SOURCE key == META_SOURCE
@ -173,6 +177,9 @@ auto meta_db::get_item_meta(const std::string &api_path, const std::string &key,
: key == META_DIRECTORY : key == META_DIRECTORY
? utils::string::from_bool( ? utils::string::from_bool(
row->get_column("directory").get_value<std::int64_t>() == 1) row->get_column("directory").get_value<std::int64_t>() == 1)
: key == META_SIZE
? std::to_string(static_cast<std::uint64_t>(
row->get_column("size").get_value<std::int64_t>()))
: json::parse( : json::parse(
row->get_column("data").get_value<std::string>())[key] row->get_column("data").get_value<std::string>())[key]
.get<std::string>(); .get<std::string>();
@ -188,10 +195,8 @@ auto meta_db::get_item_meta(const std::string &api_path, const std::string &key,
return api_error::error; return api_error::error;
} }
auto meta_db::get_pinned_files() const -> std::vector<std::string> { auto sqlite_meta_db::get_pinned_files() const -> std::vector<std::string> {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
std::vector<std::string> ret{}; std::vector<std::string> ret{};
@ -202,7 +207,7 @@ auto meta_db::get_pinned_files() const -> std::vector<std::string> {
.equals(1) .equals(1)
.go(); .go();
while (result.has_row()) { while (result.has_row()) {
std::optional<utils::db::sqlite::db_select::row> row; std::optional<utils::db::sqlite::db_result::row> row;
if (result.get_row(row) && row.has_value()) { if (result.get_row(row) && row.has_value()) {
ret.emplace_back(row->get_column("api_path").get_value<std::string>()); ret.emplace_back(row->get_column("api_path").get_value<std::string>());
} }
@ -214,10 +219,8 @@ auto meta_db::get_pinned_files() const -> std::vector<std::string> {
return ret; return ret;
} }
auto meta_db::get_total_item_count() const -> std::uint64_t { auto sqlite_meta_db::get_total_item_count() const -> std::uint64_t {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
std::uint64_t ret{}; std::uint64_t ret{};
@ -226,7 +229,7 @@ auto meta_db::get_total_item_count() const -> std::uint64_t {
.count("api_path", "count") .count("api_path", "count")
.go(); .go();
std::optional<utils::db::sqlite::db_select::row> row; std::optional<utils::db::sqlite::db_result::row> row;
if (result.get_row(row) && row.has_value()) { if (result.get_row(row) && row.has_value()) {
ret = static_cast<std::uint64_t>( ret = static_cast<std::uint64_t>(
row->get_column("count").get_value<std::int64_t>()); row->get_column("count").get_value<std::int64_t>());
@ -239,10 +242,30 @@ auto meta_db::get_total_item_count() const -> std::uint64_t {
return ret; return ret;
} }
void meta_db::remove_api_path(const std::string &api_path) { auto sqlite_meta_db::get_total_size() const -> std::uint64_t {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
}; try {
auto result = utils::db::sqlite::db_select{*db_, table_name}
.column("SUM(size) as total_size")
.where("directory")
.equals(0)
.go();
std::optional<utils::db::sqlite::db_result::row> row;
if (result.get_row(row) && row.has_value()) {
return static_cast<std::uint64_t>(
row->get_column("total_size").get_value<std::int64_t>());
}
} catch (const std::exception &e) {
utils::error::raise_error(function_name, e, "failed to get total size");
}
return 0U;
}
void sqlite_meta_db::remove_api_path(const std::string &api_path) {
REPERTORY_USES_FUNCTION_NAME();
auto result = utils::db::sqlite::db_delete{*db_, table_name} auto result = utils::db::sqlite::db_delete{*db_, table_name}
.where("api_path") .where("api_path")
@ -254,8 +277,14 @@ void meta_db::remove_api_path(const std::string &api_path) {
} }
} }
auto meta_db::remove_item_meta(const std::string &api_path, auto sqlite_meta_db::remove_item_meta(const std::string &api_path,
const std::string &key) -> api_error { const std::string &key) -> api_error {
if (key == META_DIRECTORY || key == META_PINNED || key == META_SIZE ||
key == META_SOURCE) {
// TODO log warning for unsupported attributes
return api_error::success;
}
api_meta_map meta{}; api_meta_map meta{};
auto res = get_item_meta(api_path, meta); auto res = get_item_meta(api_path, meta);
if (res != api_error::success) { if (res != api_error::success) {
@ -266,8 +295,9 @@ auto meta_db::remove_item_meta(const std::string &api_path,
return update_item_meta(api_path, meta); return update_item_meta(api_path, meta);
} }
auto meta_db::rename_item_meta(const std::string &from_api_path, auto sqlite_meta_db::rename_item_meta(const std::string &from_api_path,
const std::string &to_api_path) -> api_error { const std::string &to_api_path)
-> api_error {
api_meta_map meta{}; api_meta_map meta{};
auto res = get_item_meta(from_api_path, meta); auto res = get_item_meta(from_api_path, meta);
if (res != api_error::success) { if (res != api_error::success) {
@ -278,13 +308,14 @@ auto meta_db::rename_item_meta(const std::string &from_api_path,
return update_item_meta(to_api_path, meta); return update_item_meta(to_api_path, meta);
} }
auto meta_db::set_item_meta(const std::string &api_path, const std::string &key, auto sqlite_meta_db::set_item_meta(const std::string &api_path,
const std::string &value) -> api_error { const std::string &key,
const std::string &value) -> api_error {
return set_item_meta(api_path, {{key, value}}); return set_item_meta(api_path, {{key, value}});
} }
auto meta_db::set_item_meta(const std::string &api_path, auto sqlite_meta_db::set_item_meta(const std::string &api_path,
const api_meta_map &meta) -> api_error { const api_meta_map &meta) -> api_error {
api_meta_map existing_meta{}; api_meta_map existing_meta{};
if (get_item_meta(api_path, existing_meta) != api_error::success) { if (get_item_meta(api_path, existing_meta) != api_error::success) {
// TODO handle error // TODO handle error
@ -297,35 +328,55 @@ auto meta_db::set_item_meta(const std::string &api_path,
return update_item_meta(api_path, existing_meta); return update_item_meta(api_path, existing_meta);
} }
auto meta_db::update_item_meta(const std::string &api_path, auto sqlite_meta_db::update_item_meta(const std::string &api_path,
api_meta_map meta) -> api_error { api_meta_map meta) -> api_error {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
auto directory = utils::string::to_bool(meta[META_DIRECTORY]); try {
auto pinned = utils::string::to_bool(meta[META_PINNED]); if (meta[META_PINNED].empty()) {
auto source_path = meta[META_SOURCE]; meta[META_PINNED] = utils::string::from_bool(false);
}
if (meta[META_SIZE].empty()) {
meta[META_SIZE] = "0";
}
if (meta[META_SOURCE].empty()) {
meta[META_SOURCE] = "";
}
meta.erase(META_DIRECTORY); auto directory = utils::string::to_bool(meta.at(META_DIRECTORY));
meta.erase(META_PINNED); auto pinned =
meta.erase(META_SOURCE); directory ? false : utils::string::to_bool(meta.at(META_PINNED));
auto size = directory ? std::uint64_t(0U)
: utils::string::to_uint64(meta.at(META_SIZE));
auto source_path = directory ? std::string("") : meta.at(META_SOURCE);
auto result = utils::db::sqlite::db_insert{*db_, table_name} meta.erase(META_DIRECTORY);
.or_replace() meta.erase(META_PINNED);
.column_value("api_path", api_path) meta.erase(META_SIZE);
.column_value("data", nlohmann::json(meta).dump()) meta.erase(META_SOURCE);
.column_value("directory", directory ? 1 : 0)
.column_value("pinned", pinned ? 1 : 0) auto result = utils::db::sqlite::db_insert{*db_, table_name}
.column_value("source_path", source_path) .or_replace()
.go(); .column_value("api_path", api_path)
if (not result.ok()) { .column_value("data", nlohmann::json(meta).dump())
utils::error::raise_api_path_error(function_name, api_path, .column_value("directory", directory ? 1 : 0)
result.get_error(), .column_value("pinned", pinned ? 1 : 0)
.column_value("size", static_cast<std::int64_t>(size))
.column_value("source_path", source_path)
.go();
if (not result.ok()) {
utils::error::raise_api_path_error(function_name, api_path,
result.get_error(),
"failed to update item meta");
return api_error::error;
}
return api_error::success;
} catch (const std::exception &e) {
utils::error::raise_api_path_error(function_name, api_path, e,
"failed to update item meta"); "failed to update item meta");
return api_error::error;
} }
return api_error::success; return api_error::error;
} }
} // namespace repertory } // namespace repertory

View File

@ -0,0 +1,38 @@
/*
Copyright <2018-2024> <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.
*/
#include "db/meta_db.hpp"
#include "app_config.hpp"
#include "db/impl/rdb_meta_db.hpp"
#include "db/impl/sqlite_meta_db.hpp"
namespace repertory {
auto create_meta_db(const app_config &cfg) -> std::unique_ptr<i_meta_db> {
switch (cfg.get_database_type()) {
case database_type::sqlite:
return std::make_unique<sqlite_meta_db>(cfg);
default:
return std::make_unique<rdb_meta_db>(cfg);
}
}
} // namespace repertory

View File

@ -26,17 +26,17 @@
namespace repertory { namespace repertory {
#if !defined(_WIN32) #if !defined(_WIN32)
auto directory_iterator::fill_buffer( auto directory_iterator::fill_buffer(const remote::file_offset &offset,
const remote::file_offset &offset, fuse_fill_dir_t filler_function, fuse_fill_dir_t filler_function,
void *buffer, populate_stat_callback populate_stat) -> int { void *buffer,
static constexpr const std::string_view function_name{ populate_stat_callback populate_stat)
static_cast<const char *>(__FUNCTION__), -> int {
}; REPERTORY_USES_FUNCTION_NAME();
if (offset < items_.size()) { if (offset < items_.size()) {
try { try {
std::string item_name; std::string item_name;
struct stat st {}; struct stat st{};
struct stat *pst = nullptr; struct stat *pst = nullptr;
switch (offset) { switch (offset) {
case 0: { case 0: {
@ -115,7 +115,7 @@ auto directory_iterator::get_directory_item(const std::string &api_path,
auto directory_iterator::get_json(std::size_t offset, json &item) -> int { auto directory_iterator::get_json(std::size_t offset, json &item) -> int {
if (offset < items_.size()) { if (offset < items_.size()) {
item = items_[offset].to_json(); item = json(items_.at(offset));
return 0; return 0;
} }

View File

@ -30,46 +30,35 @@
#include "utils/file_utils.hpp" #include "utils/file_utils.hpp"
#include "utils/time.hpp" #include "utils/time.hpp"
#include "utils/utils.hpp" #include "utils/utils.hpp"
#include <spdlog/fmt/bundled/base.h>
namespace repertory { namespace repertory {
auto eviction::check_minimum_requirements(const std::string &file_path) auto eviction::check_minimum_requirements(const std::string &file_path)
-> bool { -> bool {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
auto opt_size = utils::file::file{file_path}.size(); auto file = utils::file::file{file_path};
if (not opt_size.has_value()) { auto reference_time = file.get_time(config_.get_eviction_uses_accessed_time()
utils::error::raise_error(function_name, utils::get_last_error_code(), ? utils::file::time_type::accessed
file_path, "failed to get file size"); : utils::file::time_type::modified);
return false;
}
auto file_size{opt_size.value()};
if (file_size == 0U) {
return false;
}
auto reference_time = utils::file::file{file_path}.get_time(
config_.get_eviction_uses_accessed_time()
? utils::file::time_type::accessed
: utils::file::time_type::modified);
if (not reference_time.has_value()) { if (not reference_time.has_value()) {
utils::error::raise_error(function_name, utils::get_last_error_code(),
file_path, "failed to get file time");
return false; return false;
} }
auto delay = (config_.get_eviction_delay_mins() * 60UL) * auto delay =
utils::time::NANOS_PER_SECOND; static_cast<std::uint64_t>(config_.get_eviction_delay_mins() * 60U) *
return ((reference_time.value() + static_cast<std::uint64_t>(delay)) <= utils::time::NANOS_PER_SECOND;
utils::time::get_time_now()); return (reference_time.value() + delay) <= utils::time::get_time_now();
} }
auto eviction::get_filtered_cached_files() -> std::deque<std::string> { auto eviction::get_filtered_cached_files() -> std::deque<std::string> {
auto list = auto list =
utils::file::get_directory_files(config_.get_cache_directory(), true); utils::file::get_directory_files(config_.get_cache_directory(), true);
list.erase(std::remove_if(list.begin(), list.end(), list.erase(std::remove_if(list.begin(), list.end(),
[this](const std::string &path) -> bool { [this](auto &&path) -> bool {
return not this->check_minimum_requirements(path); return not this->check_minimum_requirements(path);
}), }),
list.end()); list.end());
@ -77,69 +66,40 @@ auto eviction::get_filtered_cached_files() -> std::deque<std::string> {
} }
void eviction::service_function() { void eviction::service_function() {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
auto should_evict = true; auto cached_files_list = get_filtered_cached_files();
auto was_file_evicted{false};
while (not get_stop_requested() && not cached_files_list.empty()) {
auto file_path = cached_files_list.front();
cached_files_list.pop_front();
// Handle maximum cache size eviction try {
auto used_bytes = std::string api_path;
utils::file::directory{config_.get_cache_directory()}.size(); auto res = provider_.get_api_path_from_source(file_path, api_path);
if (config_.get_enable_max_cache_size()) { if (res != api_error::success) {
should_evict = (used_bytes > config_.get_max_cache_size_bytes()); continue;
}
if (should_evict) {
// Remove cached source files that don't meet minimum requirements
auto cached_files_list = get_filtered_cached_files();
while (not get_stop_requested() && should_evict &&
not cached_files_list.empty()) {
try {
std::string api_path;
if (provider_.get_api_path_from_source(
cached_files_list.front(), api_path) == api_error::success) {
api_file file{};
filesystem_item fsi{};
if (provider_.get_filesystem_item_and_file(api_path, file, fsi) ==
api_error::success) {
// Only evict files that match expected size
auto opt_size = utils::file::file{cached_files_list.front()}.size();
if (opt_size.has_value()) {
auto file_size{opt_size.value()};
if (file_size == fsi.size) {
// Try to evict file
if (fm_.evict_file(fsi.api_path) &&
config_.get_enable_max_cache_size()) {
// Restrict number of items evicted if maximum cache size is
// enabled
used_bytes -= file_size;
should_evict =
(used_bytes > config_.get_max_cache_size_bytes());
}
}
} else {
utils::error::raise_api_path_error(
function_name, file.api_path, file.source_path,
utils::get_last_error_code(), "failed to get file size");
}
}
}
} catch (const std::exception &ex) {
utils::error::raise_error(function_name, ex,
"failed to process cached file|sp|" +
cached_files_list.front());
} }
cached_files_list.pop_front(); if (file_mgr_.evict_file(api_path)) {
was_file_evicted = true;
}
} catch (const std::exception &ex) {
utils::error::raise_error(
function_name, ex,
fmt::format("failed to process cached file|sp|{}", file_path));
} }
} }
if (not get_stop_requested()) { if (get_stop_requested() || was_file_evicted) {
unique_mutex_lock lock(get_mutex()); return;
if (not get_stop_requested()) {
get_notify().wait_for(lock, 30s);
}
} }
unique_mutex_lock lock(get_mutex());
if (get_stop_requested()) {
return;
}
get_notify().wait_for(lock, 30s);
} }
} // namespace repertory } // namespace repertory

View File

@ -30,6 +30,7 @@
#include "initialize.hpp" #include "initialize.hpp"
#include "platform/platform.hpp" #include "platform/platform.hpp"
#include "utils/collection.hpp" #include "utils/collection.hpp"
#include "utils/error_utils.hpp"
#include "utils/file_utils.hpp" #include "utils/file_utils.hpp"
#include "utils/path.hpp" #include "utils/path.hpp"
#include "utils/string.hpp" #include "utils/string.hpp"
@ -40,47 +41,37 @@ auto fuse_base::instance() -> fuse_base & {
} }
fuse_base::fuse_base(app_config &config) : config_(config) { fuse_base::fuse_base(app_config &config) : config_(config) {
fuse_ops_.getattr = fuse_base::getattr_; fuse_ops_.access = fuse_base::access_;
fuse_ops_.mkdir = fuse_base::mkdir_;
fuse_ops_.unlink = fuse_base::unlink_;
fuse_ops_.rmdir = fuse_base::rmdir_;
fuse_ops_.rename = fuse_base::rename_;
fuse_ops_.chmod = fuse_base::chmod_; fuse_ops_.chmod = fuse_base::chmod_;
fuse_ops_.chown = fuse_base::chown_; fuse_ops_.chown = fuse_base::chown_;
fuse_ops_.truncate = fuse_base::truncate_; fuse_ops_.create = fuse_base::create_;
fuse_ops_.destroy = fuse_base::destroy_;
fuse_ops_.fallocate = fuse_base::fallocate_;
fuse_ops_.fsync = fuse_base::fsync_;
fuse_ops_.getattr = fuse_base::getattr_;
fuse_ops_.init = fuse_base::init_;
fuse_ops_.mkdir = fuse_base::mkdir_;
fuse_ops_.open = fuse_base::open_; fuse_ops_.open = fuse_base::open_;
fuse_ops_.opendir = fuse_base::opendir_;
fuse_ops_.read = fuse_base::read_; fuse_ops_.read = fuse_base::read_;
fuse_ops_.write = fuse_base::write_; fuse_ops_.readdir = fuse_base::readdir_;
fuse_ops_.release = fuse_base::release_;
fuse_ops_.releasedir = fuse_base::releasedir_;
fuse_ops_.rename = fuse_base::rename_;
fuse_ops_.rmdir = fuse_base::rmdir_;
fuse_ops_.truncate = fuse_base::truncate_;
#if !defined(__APPLE__) #if !defined(__APPLE__)
fuse_ops_.statfs = fuse_base::statfs_; fuse_ops_.statfs = fuse_base::statfs_;
#endif // __APPLE__ #endif // __APPLE__
fuse_ops_.release = fuse_base::release_; fuse_ops_.unlink = fuse_base::unlink_;
fuse_ops_.fsync = fuse_base::fsync_; fuse_ops_.utimens = fuse_base::utimens_;
fuse_ops_.write = fuse_base::write_;
#if defined(HAS_SETXATTR) #if defined(HAS_SETXATTR)
fuse_ops_.setxattr = fuse_base::setxattr_;
fuse_ops_.getxattr = fuse_base::getxattr_; fuse_ops_.getxattr = fuse_base::getxattr_;
fuse_ops_.listxattr = fuse_base::listxattr_; fuse_ops_.listxattr = fuse_base::listxattr_;
fuse_ops_.removexattr = fuse_base::removexattr_; fuse_ops_.removexattr = fuse_base::removexattr_;
#endif // HAS_SETXATTR fuse_ops_.setxattr = fuse_base::setxattr_;
fuse_ops_.opendir = fuse_base::opendir_; #endif // defined(HAS_SETXATTR)
fuse_ops_.readdir = fuse_base::readdir_;
fuse_ops_.releasedir = fuse_base::releasedir_;
fuse_ops_.init = fuse_base::init_;
fuse_ops_.destroy = fuse_base::destroy_;
fuse_ops_.access = fuse_base::access_;
fuse_ops_.create = fuse_base::create_;
#if FUSE_USE_VERSION < 30
fuse_ops_.ftruncate = fuse_base::ftruncate_;
fuse_ops_.fgetattr = fuse_base::fgetattr_;
#endif
fuse_ops_.utimens = fuse_base::utimens_;
#if FUSE_USE_VERSION < 30
fuse_ops_.flag_nullpath_ok = 0;
fuse_ops_.flag_nopath = 0;
fuse_ops_.flag_utime_omit_ok = 1;
fuse_ops_.flag_reserved = 0;
#endif
fuse_ops_.fallocate = fuse_base::fallocate_;
#if defined(__APPLE__) #if defined(__APPLE__)
fuse_ops_.chflags = fuse_base::chflags_; fuse_ops_.chflags = fuse_base::chflags_;
fuse_ops_.fsetattr_x = fuse_base::fsetattr_x_; fuse_ops_.fsetattr_x = fuse_base::fsetattr_x_;
@ -91,7 +82,13 @@ fuse_base::fuse_base(app_config &config) : config_(config) {
fuse_ops_.setcrtime = fuse_base::setcrtime_; fuse_ops_.setcrtime = fuse_base::setcrtime_;
fuse_ops_.setvolname = fuse_base::setvolname_; fuse_ops_.setvolname = fuse_base::setvolname_;
fuse_ops_.statfs_x = fuse_base::statfs_x_; fuse_ops_.statfs_x = fuse_base::statfs_x_;
#endif // __APPLE__ #endif // defined(__APPLE__)
#if FUSE_USE_VERSION < 30
fuse_ops_.flag_nullpath_ok = 0;
fuse_ops_.flag_nopath = 0;
fuse_ops_.flag_utime_omit_ok = 1;
fuse_ops_.flag_reserved = 0;
#endif // FUSE_USE_VERSION < 30
E_SUBSCRIBE_EXACT(unmount_requested, [this](const unmount_requested &) { E_SUBSCRIBE_EXACT(unmount_requested, [this](const unmount_requested &) {
std::thread([this]() { this->shutdown(); }).detach(); std::thread([this]() { this->shutdown(); }).detach();
@ -101,9 +98,7 @@ fuse_base::fuse_base(app_config &config) : config_(config) {
fuse_base::~fuse_base() { E_CONSUMER_RELEASE(); } fuse_base::~fuse_base() { E_CONSUMER_RELEASE(); }
auto fuse_base::access_(const char *path, int mask) -> int { auto fuse_base::access_(const char *path, int mask) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().instance().execute_callback( return instance().instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -113,9 +108,7 @@ auto fuse_base::access_(const char *path, int mask) -> int {
#if defined(__APPLE__) #if defined(__APPLE__)
auto fuse_base::chflags_(const char *path, uint32_t flags) -> int { auto fuse_base::chflags_(const char *path, uint32_t flags) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().instance().execute_callback( return instance().instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -127,9 +120,7 @@ auto fuse_base::chflags_(const char *path, uint32_t flags) -> int {
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
auto fuse_base::chmod_(const char *path, mode_t mode, auto fuse_base::chmod_(const char *path, mode_t mode,
struct fuse_file_info *fi) -> int { struct fuse_file_info *fi) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -138,9 +129,7 @@ auto fuse_base::chmod_(const char *path, mode_t mode,
} }
#else #else
auto fuse_base::chmod_(const char *path, mode_t mode) -> int { auto fuse_base::chmod_(const char *path, mode_t mode) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -152,9 +141,7 @@ auto fuse_base::chmod_(const char *path, mode_t mode) -> int {
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
auto fuse_base::chown_(const char *path, uid_t uid, gid_t gid, auto fuse_base::chown_(const char *path, uid_t uid, gid_t gid,
struct fuse_file_info *fi) -> int { struct fuse_file_info *fi) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -163,9 +150,7 @@ auto fuse_base::chown_(const char *path, uid_t uid, gid_t gid,
} }
#else #else
auto fuse_base::chown_(const char *path, uid_t uid, gid_t gid) -> int { auto fuse_base::chown_(const char *path, uid_t uid, gid_t gid) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -176,9 +161,7 @@ auto fuse_base::chown_(const char *path, uid_t uid, gid_t gid) -> int {
auto fuse_base::create_(const char *path, mode_t mode, auto fuse_base::create_(const char *path, mode_t mode,
struct fuse_file_info *fi) -> int { struct fuse_file_info *fi) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -187,9 +170,7 @@ auto fuse_base::create_(const char *path, mode_t mode,
} }
void fuse_base::destroy_(void *ptr) { void fuse_base::destroy_(void *ptr) {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
execute_void_callback(function_name, [&]() { instance().destroy_impl(ptr); }); execute_void_callback(function_name, [&]() { instance().destroy_impl(ptr); });
} }
@ -264,9 +245,7 @@ auto fuse_base::execute_void_pointer_callback(std::string_view function_name,
auto fuse_base::fallocate_(const char *path, int mode, off_t offset, auto fuse_base::fallocate_(const char *path, int mode, off_t offset,
off_t length, struct fuse_file_info *fi) -> int { off_t length, struct fuse_file_info *fi) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -278,9 +257,7 @@ auto fuse_base::fallocate_(const char *path, int mode, off_t offset,
#if FUSE_USE_VERSION < 30 #if FUSE_USE_VERSION < 30
auto fuse_base::fgetattr_(const char *path, struct stat *st, auto fuse_base::fgetattr_(const char *path, struct stat *st,
struct fuse_file_info *fi) -> int { struct fuse_file_info *fi) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -292,9 +269,7 @@ auto fuse_base::fgetattr_(const char *path, struct stat *st,
#if defined(__APPLE__) #if defined(__APPLE__)
auto fuse_base::fsetattr_x_(const char *path, struct setattr_x *attr, auto fuse_base::fsetattr_x_(const char *path, struct setattr_x *attr,
struct fuse_file_info *fi) -> int { struct fuse_file_info *fi) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -305,9 +280,7 @@ auto fuse_base::fsetattr_x_(const char *path, struct setattr_x *attr,
auto fuse_base::fsync_(const char *path, int datasync, auto fuse_base::fsync_(const char *path, int datasync,
struct fuse_file_info *fi) -> int { struct fuse_file_info *fi) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -318,9 +291,7 @@ auto fuse_base::fsync_(const char *path, int datasync,
#if FUSE_USE_VERSION < 30 #if FUSE_USE_VERSION < 30
auto fuse_base::ftruncate_(const char *path, off_t size, auto fuse_base::ftruncate_(const char *path, off_t size,
struct fuse_file_info *fi) -> int { struct fuse_file_info *fi) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -332,9 +303,7 @@ auto fuse_base::ftruncate_(const char *path, off_t size,
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
auto fuse_base::getattr_(const char *path, struct stat *st, auto fuse_base::getattr_(const char *path, struct stat *st,
struct fuse_file_info *fi) -> int { struct fuse_file_info *fi) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -343,9 +312,7 @@ auto fuse_base::getattr_(const char *path, struct stat *st,
} }
#else #else
auto fuse_base::getattr_(const char *path, struct stat *st) -> int { auto fuse_base::getattr_(const char *path, struct stat *st) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -357,9 +324,7 @@ auto fuse_base::getattr_(const char *path, struct stat *st) -> int {
#if defined(__APPLE__) #if defined(__APPLE__)
auto fuse_base::getxtimes_(const char *path, struct timespec *bkuptime, auto fuse_base::getxtimes_(const char *path, struct timespec *bkuptime,
struct timespec *crtime) -> int { struct timespec *crtime) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -371,9 +336,7 @@ auto fuse_base::getxtimes_(const char *path, struct timespec *bkuptime,
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
auto fuse_base::init_(struct fuse_conn_info *conn, auto fuse_base::init_(struct fuse_conn_info *conn,
struct fuse_config *cfg) -> void * { struct fuse_config *cfg) -> void * {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return execute_void_pointer_callback(function_name, [&]() -> void * { return execute_void_pointer_callback(function_name, [&]() -> void * {
return instance().init_impl(conn, cfg); return instance().init_impl(conn, cfg);
@ -381,9 +344,7 @@ auto fuse_base::init_(struct fuse_conn_info *conn,
} }
#else #else
auto fuse_base::init_(struct fuse_conn_info *conn) -> void * { auto fuse_base::init_(struct fuse_conn_info *conn) -> void * {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return execute_void_pointer_callback( return execute_void_pointer_callback(
function_name, [&]() -> void * { return instance().init_impl(conn); }); function_name, [&]() -> void * { return instance().init_impl(conn); });
@ -396,9 +357,7 @@ auto fuse_base::init_impl([[maybe_unused]] struct fuse_conn_info *conn,
#else // FUSE_USE_VERSION < 30 #else // FUSE_USE_VERSION < 30
auto fuse_base::init_impl(struct fuse_conn_info *conn) -> void * { auto fuse_base::init_impl(struct fuse_conn_info *conn) -> void * {
#endif // FUSE_USE_VERSION >= 30 #endif // FUSE_USE_VERSION >= 30
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
#if defined(__APPLE__) #if defined(__APPLE__)
conn->want |= FUSE_CAP_VOL_RENAME; conn->want |= FUSE_CAP_VOL_RENAME;
@ -426,9 +385,7 @@ auto fuse_base::init_impl(struct fuse_conn_info *conn) -> void * {
} }
auto fuse_base::mkdir_(const char *path, mode_t mode) -> int { auto fuse_base::mkdir_(const char *path, mode_t mode) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -485,9 +442,7 @@ auto fuse_base::mount(std::vector<std::string> args) -> int {
} }
auto fuse_base::open_(const char *path, struct fuse_file_info *fi) -> int { auto fuse_base::open_(const char *path, struct fuse_file_info *fi) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -496,9 +451,7 @@ auto fuse_base::open_(const char *path, struct fuse_file_info *fi) -> int {
} }
auto fuse_base::opendir_(const char *path, struct fuse_file_info *fi) -> int { auto fuse_base::opendir_(const char *path, struct fuse_file_info *fi) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -508,9 +461,7 @@ auto fuse_base::opendir_(const char *path, struct fuse_file_info *fi) -> int {
auto fuse_base::read_(const char *path, char *buffer, size_t read_size, auto fuse_base::read_(const char *path, char *buffer, size_t read_size,
off_t read_offset, struct fuse_file_info *fi) -> int { off_t read_offset, struct fuse_file_info *fi) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
std::size_t bytes_read{}; std::size_t bytes_read{};
const auto res = instance().execute_callback( const auto res = instance().execute_callback(
@ -528,9 +479,7 @@ auto fuse_base::readdir_(const char *path, void *buf,
fuse_fill_dir_t fuse_fill_dir, off_t offset, fuse_fill_dir_t fuse_fill_dir, off_t offset,
struct fuse_file_info *fi, struct fuse_file_info *fi,
fuse_readdir_flags flags) -> int { fuse_readdir_flags flags) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -542,9 +491,7 @@ auto fuse_base::readdir_(const char *path, void *buf,
auto fuse_base::readdir_(const char *path, void *buf, auto fuse_base::readdir_(const char *path, void *buf,
fuse_fill_dir_t fuse_fill_dir, off_t offset, fuse_fill_dir_t fuse_fill_dir, off_t offset,
struct fuse_file_info *fi) -> int { struct fuse_file_info *fi) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -555,9 +502,7 @@ auto fuse_base::readdir_(const char *path, void *buf,
#endif #endif
auto fuse_base::release_(const char *path, struct fuse_file_info *fi) -> int { auto fuse_base::release_(const char *path, struct fuse_file_info *fi) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -567,9 +512,7 @@ auto fuse_base::release_(const char *path, struct fuse_file_info *fi) -> int {
auto fuse_base::releasedir_(const char *path, auto fuse_base::releasedir_(const char *path,
struct fuse_file_info *fi) -> int { struct fuse_file_info *fi) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -580,9 +523,7 @@ auto fuse_base::releasedir_(const char *path,
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
auto fuse_base::rename_(const char *from, const char *to, auto fuse_base::rename_(const char *from, const char *to,
unsigned int flags) -> int { unsigned int flags) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, from, to, function_name, from, to,
@ -593,9 +534,7 @@ auto fuse_base::rename_(const char *from, const char *to,
} }
#else #else
auto fuse_base::rename_(const char *from, const char *to) -> int { auto fuse_base::rename_(const char *from, const char *to) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, from, to, function_name, from, to,
@ -607,9 +546,7 @@ auto fuse_base::rename_(const char *from, const char *to) -> int {
#endif #endif
auto fuse_base::rmdir_(const char *path) -> int { auto fuse_base::rmdir_(const char *path) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -621,9 +558,7 @@ auto fuse_base::rmdir_(const char *path) -> int {
#if defined(__APPLE__) #if defined(__APPLE__)
auto fuse_base::getxattr_(const char *path, const char *name, char *value, auto fuse_base::getxattr_(const char *path, const char *name, char *value,
size_t size, uint32_t position) -> int { size_t size, uint32_t position) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
int attribute_size = 0; int attribute_size = 0;
const auto res = instance().execute_callback( const auto res = instance().execute_callback(
@ -637,9 +572,7 @@ auto fuse_base::getxattr_(const char *path, const char *name, char *value,
#else // __APPLE__ #else // __APPLE__
auto fuse_base::getxattr_(const char *path, const char *name, char *value, auto fuse_base::getxattr_(const char *path, const char *name, char *value,
size_t size) -> int { size_t size) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
int attribute_size = 0; int attribute_size = 0;
const auto res = instance().execute_callback( const auto res = instance().execute_callback(
@ -653,9 +586,7 @@ auto fuse_base::getxattr_(const char *path, const char *name, char *value,
#endif // __APPLE__ #endif // __APPLE__
auto fuse_base::listxattr_(const char *path, char *buffer, size_t size) -> int { auto fuse_base::listxattr_(const char *path, char *buffer, size_t size) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
int required_size = 0; int required_size = 0;
bool return_size = false; bool return_size = false;
@ -775,9 +706,7 @@ void fuse_base::raise_fuse_event(std::string_view function_name,
} }
auto fuse_base::removexattr_(const char *path, const char *name) -> int { auto fuse_base::removexattr_(const char *path, const char *name) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -788,9 +717,7 @@ auto fuse_base::removexattr_(const char *path, const char *name) -> int {
#if defined(__APPLE__) #if defined(__APPLE__)
auto fuse_base::setxattr_(const char *path, const char *name, const char *value, auto fuse_base::setxattr_(const char *path, const char *name, const char *value,
size_t size, int flags, uint32_t position) -> int { size_t size, int flags, uint32_t position) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto res = instance().execute_callback( const auto res = instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -806,9 +733,7 @@ auto fuse_base::setxattr_(const char *path, const char *name, const char *value,
#else // __APPLE__ #else // __APPLE__
auto fuse_base::setxattr_(const char *path, const char *name, const char *value, auto fuse_base::setxattr_(const char *path, const char *name, const char *value,
size_t size, int flags) -> int { size_t size, int flags) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto res = instance().execute_callback( const auto res = instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -832,9 +757,7 @@ void fuse_base::shutdown() {
#if defined(__APPLE__) #if defined(__APPLE__)
auto fuse_base::setattr_x_(const char *path, struct setattr_x *attr) -> int { auto fuse_base::setattr_x_(const char *path, struct setattr_x *attr) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -844,9 +767,7 @@ auto fuse_base::setattr_x_(const char *path, struct setattr_x *attr) -> int {
auto fuse_base::setbkuptime_(const char *path, auto fuse_base::setbkuptime_(const char *path,
const struct timespec *bkuptime) -> int { const struct timespec *bkuptime) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -856,9 +777,7 @@ auto fuse_base::setbkuptime_(const char *path,
auto fuse_base::setchgtime_(const char *path, auto fuse_base::setchgtime_(const char *path,
const struct timespec *chgtime) -> int { const struct timespec *chgtime) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -868,9 +787,7 @@ auto fuse_base::setchgtime_(const char *path,
auto fuse_base::setcrtime_(const char *path, auto fuse_base::setcrtime_(const char *path,
const struct timespec *crtime) -> int { const struct timespec *crtime) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -879,9 +796,7 @@ auto fuse_base::setcrtime_(const char *path,
} }
auto fuse_base::setvolname_(const char *volname) -> int { auto fuse_base::setvolname_(const char *volname) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, volname, [&](std::string api_path) -> api_error { function_name, volname, [&](std::string api_path) -> api_error {
@ -890,9 +805,7 @@ auto fuse_base::setvolname_(const char *volname) -> int {
} }
auto fuse_base::statfs_x_(const char *path, struct statfs *stbuf) -> int { auto fuse_base::statfs_x_(const char *path, struct statfs *stbuf) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -901,9 +814,7 @@ auto fuse_base::statfs_x_(const char *path, struct statfs *stbuf) -> int {
} }
#else // __APPLE__ #else // __APPLE__
auto fuse_base::statfs_(const char *path, struct statvfs *stbuf) -> int { auto fuse_base::statfs_(const char *path, struct statvfs *stbuf) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -915,9 +826,7 @@ auto fuse_base::statfs_(const char *path, struct statvfs *stbuf) -> int {
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
auto fuse_base::truncate_(const char *path, off_t size, auto fuse_base::truncate_(const char *path, off_t size,
struct fuse_file_info *fi) -> int { struct fuse_file_info *fi) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -926,9 +835,7 @@ auto fuse_base::truncate_(const char *path, off_t size,
} }
#else #else
auto fuse_base::truncate_(const char *path, off_t size) -> int { auto fuse_base::truncate_(const char *path, off_t size) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -938,9 +845,7 @@ auto fuse_base::truncate_(const char *path, off_t size) -> int {
#endif #endif
auto fuse_base::unlink_(const char *path) -> int { auto fuse_base::unlink_(const char *path) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -965,9 +870,7 @@ auto fuse_base::unmount(const std::string &mount_location) -> int {
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
auto fuse_base::utimens_(const char *path, const struct timespec tv[2], auto fuse_base::utimens_(const char *path, const struct timespec tv[2],
struct fuse_file_info *fi) -> int { struct fuse_file_info *fi) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -976,9 +879,7 @@ auto fuse_base::utimens_(const char *path, const struct timespec tv[2],
} }
#else #else
auto fuse_base::utimens_(const char *path, const struct timespec tv[2]) -> int { auto fuse_base::utimens_(const char *path, const struct timespec tv[2]) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
return instance().execute_callback( return instance().execute_callback(
function_name, path, [&](std::string api_path) -> api_error { function_name, path, [&](std::string api_path) -> api_error {
@ -989,9 +890,7 @@ auto fuse_base::utimens_(const char *path, const struct timespec tv[2]) -> int {
auto fuse_base::write_(const char *path, const char *buffer, size_t write_size, auto fuse_base::write_(const char *path, const char *buffer, size_t write_size,
off_t write_offset, struct fuse_file_info *fi) -> int { off_t write_offset, struct fuse_file_info *fi) -> int {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
std::size_t bytes_written{}; std::size_t bytes_written{};

View File

@ -67,6 +67,11 @@ auto fuse_drive::chmod_impl(std::string api_path, mode_t mode,
auto fuse_drive::chmod_impl(std::string api_path, mode_t mode) -> api_error { auto fuse_drive::chmod_impl(std::string api_path, mode_t mode) -> api_error {
#endif // FUSE_USE_VERSION >= 30 #endif // FUSE_USE_VERSION >= 30
return check_and_perform(api_path, X_OK, [&](api_meta_map &) -> api_error { return check_and_perform(api_path, X_OK, [&](api_meta_map &) -> api_error {
if (((mode & (S_ISGID | S_ISUID | S_ISVTX)) != 0) &&
(get_effective_uid() != 0)) {
return api_error::permission_denied;
}
return provider_.set_item_meta(api_path, META_MODE, std::to_string(mode)); return provider_.set_item_meta(api_path, META_MODE, std::to_string(mode));
}); });
} }
@ -79,44 +84,48 @@ auto fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid,
auto fuse_drive::chown_impl(std::string api_path, uid_t uid, auto fuse_drive::chown_impl(std::string api_path, uid_t uid,
gid_t gid) -> api_error { gid_t gid) -> api_error {
#endif #endif
return check_and_perform(api_path, X_OK, return check_and_perform(
[&](api_meta_map &meta) -> api_error { api_path, X_OK, [&](api_meta_map &meta) -> api_error {
meta.clear(); meta.clear();
if (uid != static_cast<uid_t>(-1)) { if (uid != static_cast<uid_t>(-1)) {
meta[META_UID] = std::to_string(uid); if (get_effective_uid() != 0 && get_effective_uid() != uid) {
} return api_error::permission_denied;
}
if (gid != static_cast<gid_t>(-1)) { meta[META_UID] = std::to_string(uid);
meta[META_GID] = std::to_string(gid); }
}
if (not meta.empty()) { if (gid != static_cast<gid_t>(-1)) {
return provider_.set_item_meta(api_path, meta); if (get_effective_uid() != 0 &&
} not utils::is_uid_member_of_group(get_effective_uid(), gid)) {
return api_error::permission_denied;
}
return api_error::success; meta[META_GID] = std::to_string(gid);
}); }
if (meta.empty()) {
return api_error::success;
}
return provider_.set_item_meta(api_path, meta);
});
} }
auto fuse_drive::create_impl(std::string api_path, mode_t mode, auto fuse_drive::create_impl(std::string api_path, mode_t mode,
struct fuse_file_info *file_info) -> api_error { struct fuse_file_info *file_info) -> api_error {
file_info->fh = 0U; file_info->fh = 0U;
const auto is_directory_op = auto is_append_op = ((file_info->flags & O_APPEND) == O_APPEND);
((file_info->flags & O_DIRECTORY) == O_DIRECTORY); auto is_create_op = ((file_info->flags & O_CREAT) == O_CREAT);
const auto is_create_op = ((file_info->flags & O_CREAT) == O_CREAT); auto is_directory_op = ((file_info->flags & O_DIRECTORY) == O_DIRECTORY);
const auto is_truncate_op = (((file_info->flags & O_TRUNC) != 0) && auto is_exclusive = ((file_info->flags & O_EXCL) == O_EXCL);
(((file_info->flags & O_WRONLY) != 0) || auto is_read_write_op = ((file_info->flags & O_RDWR) == O_RDWR);
((file_info->flags & O_RDWR) != 0))); auto is_truncate_op = ((file_info->flags & O_TRUNC) == O_TRUNC);
auto is_write_only_op = ((file_info->flags & O_WRONLY) == O_WRONLY);
if (((file_info->flags & O_WRONLY) != 0) || if (is_create_op && is_append_op && is_truncate_op) {
((file_info->flags & O_RDWR) != 0)) { return api_error::invalid_operation;
const auto res = provider_.is_file_writeable(api_path)
? api_error::success
: api_error::permission_denied;
if (res != api_error::success) {
return res;
}
} }
auto res = check_parent_access(api_path, X_OK); auto res = check_parent_access(api_path, X_OK);
@ -125,37 +134,65 @@ auto fuse_drive::create_impl(std::string api_path, mode_t mode,
} }
if (is_create_op) { if (is_create_op) {
if ((res = check_access(api_path, W_OK)) == api_error::item_not_found) { res = check_access(api_path, W_OK);
if (res == api_error::item_not_found) {
res = check_parent_access(api_path, W_OK); res = check_parent_access(api_path, W_OK);
} }
} else if ((res = check_access(api_path, R_OK)) == } else {
api_error::item_not_found) { res = check_access(api_path, R_OK);
res = check_parent_access(api_path, R_OK); if (res == api_error::item_not_found) {
res = check_parent_access(api_path, R_OK);
}
} }
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
if ((is_write_only_op || is_read_write_op) &&
not provider_.is_file_writeable(api_path)) {
return api_error::permission_denied;
}
if (is_create_op && is_directory_op) { if (is_create_op && is_directory_op) {
return api_error::invalid_operation; return api_error::invalid_operation;
} }
if (not is_create_op) { bool file_exists{};
bool dir_exists{}; res = provider_.is_file(api_path, file_exists);
if (res != api_error::success) {
return res;
}
bool dir_exists{};
if (not file_exists) {
res = provider_.is_directory(api_path, dir_exists); res = provider_.is_directory(api_path, dir_exists);
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
}
bool file_exists{}; if (is_create_op) {
res = provider_.is_file(api_path, file_exists); if (dir_exists) {
if (res != api_error::success) { return api_error::directory_exists;
return res;
} }
if (is_exclusive && file_exists) {
return api_error::item_exists;
}
} else {
if (is_directory_op ? file_exists : dir_exists) {
return is_directory_op ? api_error::item_exists
: api_error::directory_exists;
}
if (not(is_directory_op ? dir_exists : file_exists)) { if (not(is_directory_op ? dir_exists : file_exists)) {
return (is_directory_op ? api_error::directory_not_found return is_directory_op ? api_error::directory_not_found
: api_error::item_not_found); : api_error::item_not_found;
}
if ((is_exclusive || is_truncate_op) && not file_exists) {
return api_error::item_not_found;
} }
} }
@ -163,17 +200,16 @@ auto fuse_drive::create_impl(std::string api_path, mode_t mode,
{ {
std::shared_ptr<i_open_file> open_file; std::shared_ptr<i_open_file> open_file;
if (is_create_op) { if (is_create_op) {
const auto now = utils::time::get_time_now(); auto now = utils::time::get_time_now();
#if defined(__APPLE__) #if defined(__APPLE__)
const auto osx_flags = static_cast<std::uint32_t>(file_info->flags); auto osx_flags = static_cast<std::uint32_t>(file_info->flags);
#else // !defined(__APPLE__) #else // !defined(__APPLE__)
const auto osx_flags = 0U; auto osx_flags = 0U;
#endif // defined(__APPLE__) #endif // defined(__APPLE__)
auto meta = create_meta_attributes( auto meta = create_meta_attributes(
now, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE, now, now, now, FILE_ATTRIBUTE_ARCHIVE, now, now, is_directory_op,
is_directory_op, get_effective_gid(), "", mode, now, 0U, osx_flags, get_effective_gid(), "", mode, now, 0U, osx_flags, 0U,
0U,
utils::path::combine(config_.get_cache_directory(), utils::path::combine(config_.get_cache_directory(),
{utils::create_uuid_string()}), {utils::create_uuid_string()}),
get_effective_uid(), now); get_effective_uid(), now);
@ -182,19 +218,24 @@ auto fuse_drive::create_impl(std::string api_path, mode_t mode,
if ((res != api_error::item_exists) && (res != api_error::success)) { if ((res != api_error::item_exists) && (res != api_error::success)) {
return res; return res;
} }
} else if (((res = fm_->open(api_path, is_directory_op, file_info->flags, } else {
handle, open_file)) != api_error::success)) { res = fm_->open(api_path, is_directory_op, file_info->flags, handle,
return res; open_file);
if (res != api_error::success) {
return res;
}
} }
} }
file_info->fh = handle; file_info->fh = handle;
if (is_truncate_op) { if (is_truncate_op) {
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
if ((res = truncate_impl(api_path, 0, file_info)) != api_error::success) { res = truncate_impl(api_path, 0, file_info);
#else if (res != api_error::success) {
if ((res = ftruncate_impl(api_path, 0, file_info)) != api_error::success) { #else // FUSE_USE_VERSION < 30
#endif res = ftruncate_impl(api_path, 0, file_info);
if (res != api_error::success) {
#endif // FUSE_USE_VERSION >= 30
fm_->close(handle); fm_->close(handle);
file_info->fh = 0U; file_info->fh = 0U;
errno = std::abs(utils::from_api_error(res)); errno = std::abs(utils::from_api_error(res));
@ -206,9 +247,7 @@ auto fuse_drive::create_impl(std::string api_path, mode_t mode,
} }
void fuse_drive::destroy_impl(void *ptr) { void fuse_drive::destroy_impl(void *ptr) {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
event_system::instance().raise<drive_unmount_pending>(get_mount_location()); event_system::instance().raise<drive_unmount_pending>(get_mount_location());
@ -265,9 +304,9 @@ auto fuse_drive::fallocate_impl(std::string /*api_path*/, int mode,
return res; return res;
} }
if ((res = check_open_flags( res = check_open_flags(open_file->get_open_data(file_info->fh),
open_file->get_open_data(file_info->fh), O_WRONLY | O_APPEND, O_WRONLY | O_APPEND, api_error::invalid_handle);
api_error::invalid_handle)) != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
@ -311,7 +350,7 @@ auto fuse_drive::fallocate_impl(std::string /*api_path*/, int mode,
static_cast<std::uint64_t>(offset + length), allocator); static_cast<std::uint64_t>(offset + length), allocator);
} }
auto fuse_drive::fgetattr_impl(std::string api_path, struct stat *st, auto fuse_drive::fgetattr_impl(std::string api_path, struct stat *unix_st,
struct fuse_file_info *file_info) -> api_error { struct fuse_file_info *file_info) -> api_error {
std::shared_ptr<i_open_file> open_file; std::shared_ptr<i_open_file> open_file;
if (not fm_->get_open_file(file_info->fh, false, open_file)) { if (not fm_->get_open_file(file_info->fh, false, open_file)) {
@ -330,7 +369,7 @@ auto fuse_drive::fgetattr_impl(std::string api_path, struct stat *st,
return res; return res;
} }
fuse_drive_base::populate_stat(api_path, open_file->get_file_size(), meta, fuse_drive_base::populate_stat(api_path, open_file->get_file_size(), meta,
directory, provider_, st); directory, provider_, unix_st);
return api_error::success; return api_error::success;
} }
@ -377,8 +416,8 @@ api_error fuse_drive::ftruncate_impl(std::string /*api_path*/, off_t size,
return api_error::invalid_handle; return api_error::invalid_handle;
} }
const auto res = check_writeable(f->get_open_data(file_info->fh), auto res = check_writeable(f->get_open_data(file_info->fh),
api_error::invalid_handle); api_error::invalid_handle);
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
@ -394,9 +433,7 @@ auto fuse_drive::get_directory_item_count(const std::string &api_path) const
auto fuse_drive::get_directory_items(const std::string &api_path) const auto fuse_drive::get_directory_items(const std::string &api_path) const
-> directory_item_list { -> directory_item_list {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
directory_item_list list{}; directory_item_list list{};
auto res = provider_.get_directory_items(api_path, list); auto res = provider_.get_directory_items(api_path, list);
@ -410,9 +447,7 @@ auto fuse_drive::get_directory_items(const std::string &api_path) const
auto fuse_drive::get_file_size(const std::string &api_path) const auto fuse_drive::get_file_size(const std::string &api_path) const
-> std::uint64_t { -> std::uint64_t {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
std::uint64_t file_size{}; std::uint64_t file_size{};
auto res = provider_.get_file_size(api_path, file_size); auto res = provider_.get_file_size(api_path, file_size);
@ -433,7 +468,7 @@ auto fuse_drive::get_item_meta(const std::string &api_path,
const std::string &name, const std::string &name,
std::string &value) const -> api_error { std::string &value) const -> api_error {
api_meta_map meta{}; api_meta_map meta{};
const auto ret = get_item_meta(api_path, meta); auto ret = get_item_meta(api_path, meta);
if (ret == api_error::success) { if (ret == api_error::success) {
value = meta[name]; value = meta[name];
} }
@ -442,14 +477,14 @@ auto fuse_drive::get_item_meta(const std::string &api_path,
} }
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
auto fuse_drive::getattr_impl(std::string api_path, struct stat *st, auto fuse_drive::getattr_impl(std::string api_path, struct stat *unix_st,
struct fuse_file_info * /*file_info*/) struct fuse_file_info * /*file_info*/)
-> api_error { -> api_error {
#else #else
auto fuse_drive::getattr_impl(std::string api_path, auto fuse_drive::getattr_impl(std::string api_path,
struct stat *st) -> api_error { struct stat *unix_st) -> api_error {
#endif #endif
const auto parent = utils::path::get_parent_api_path(api_path); auto parent = utils::path::get_parent_api_path(api_path);
auto res = check_parent_access(api_path, X_OK); auto res = check_parent_access(api_path, X_OK);
if (res != api_error::success) { if (res != api_error::success) {
@ -459,16 +494,17 @@ auto fuse_drive::getattr_impl(std::string api_path,
auto found = false; auto found = false;
directory_cache_->execute_action(parent, [&](directory_iterator &iter) { directory_cache_->execute_action(parent, [&](directory_iterator &iter) {
directory_item dir_item{}; directory_item dir_item{};
if ((found = (iter.get_directory_item(api_path, dir_item) == found = (iter.get_directory_item(api_path, dir_item) == api_error::success);
api_error::success))) { if (found) {
fuse_drive_base::populate_stat(api_path, dir_item.size, dir_item.meta, fuse_drive_base::populate_stat(api_path, dir_item.size, dir_item.meta,
dir_item.directory, provider_, st); dir_item.directory, provider_, unix_st);
} }
}); });
if (not found) { if (not found) {
api_meta_map meta{}; api_meta_map meta{};
if ((res = provider_.get_item_meta(api_path, meta)) != api_error::success) { res = provider_.get_item_meta(api_path, meta);
if (res != api_error::success) {
return res; return res;
} }
@ -479,7 +515,7 @@ auto fuse_drive::getattr_impl(std::string api_path,
} }
fuse_drive_base::populate_stat(api_path, fuse_drive_base::populate_stat(api_path,
utils::string::to_uint64(meta[META_SIZE]), utils::string::to_uint64(meta[META_SIZE]),
meta, directory, provider_, st); meta, directory, provider_, unix_st);
} }
return api_error::success; return api_error::success;
@ -534,9 +570,7 @@ auto fuse_drive::init_impl(struct fuse_conn_info *conn,
#else #else
void *fuse_drive::init_impl(struct fuse_conn_info *conn) { void *fuse_drive::init_impl(struct fuse_conn_info *conn) {
#endif #endif
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
auto *ret = fuse_drive_base::init_impl(conn, cfg); auto *ret = fuse_drive_base::init_impl(conn, cfg);
@ -554,11 +588,9 @@ void *fuse_drive::init_impl(struct fuse_conn_info *conn) {
event_system::instance().start(); event_system::instance().start();
was_mounted_ = true; was_mounted_ = true;
polling::instance().start(&config_);
fm_ = std::make_unique<file_manager>(config_, provider_); fm_ = std::make_unique<file_manager>(config_, provider_);
server_ = std::make_unique<full_server>(config_, provider_, *fm_); server_ = std::make_unique<full_server>(config_, provider_, *fm_);
if (not provider_.is_direct_only()) { if (not provider_.is_read_only()) {
eviction_ = std::make_unique<eviction>(provider_, config_, *fm_); eviction_ = std::make_unique<eviction>(provider_, config_, *fm_);
} }
directory_cache_ = std::make_unique<directory_cache>(); directory_cache_ = std::make_unique<directory_cache>();
@ -580,7 +612,7 @@ void *fuse_drive::init_impl(struct fuse_conn_info *conn) {
eviction_->start(); eviction_->start();
} }
if (config_.get_enable_remote_mount()) { if (config_.get_remote_mount().enable) {
remote_server_ = std::make_unique<remote_fuse::remote_server>( remote_server_ = std::make_unique<remote_fuse::remote_server>(
config_, *this, get_mount_location()); config_, *this, get_mount_location());
} }
@ -588,6 +620,9 @@ void *fuse_drive::init_impl(struct fuse_conn_info *conn) {
if (not lock_data_.set_mount_state(true, get_mount_location(), getpid())) { if (not lock_data_.set_mount_state(true, get_mount_location(), getpid())) {
utils::error::raise_error(function_name, "failed to set mount state"); utils::error::raise_error(function_name, "failed to set mount state");
} }
polling::instance().start(&config_);
event_system::instance().raise<drive_mounted>(get_mount_location()); event_system::instance().raise<drive_mounted>(get_mount_location());
} catch (const std::exception &e) { } catch (const std::exception &e) {
utils::error::raise_error(function_name, e, "exception during fuse init"); utils::error::raise_error(function_name, e, "exception during fuse init");
@ -605,16 +640,14 @@ auto fuse_drive::is_processing(const std::string &api_path) const -> bool {
} }
auto fuse_drive::mkdir_impl(std::string api_path, mode_t mode) -> api_error { auto fuse_drive::mkdir_impl(std::string api_path, mode_t mode) -> api_error {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
auto res = check_parent_access(api_path, W_OK | X_OK); auto res = check_parent_access(api_path, W_OK | X_OK);
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
const auto now = utils::time::get_time_now(); auto now = utils::time::get_time_now();
auto meta = create_meta_attributes(now, FILE_ATTRIBUTE_DIRECTORY, now, now, auto meta = create_meta_attributes(now, FILE_ATTRIBUTE_DIRECTORY, now, now,
true, get_effective_gid(), "", mode, now, true, get_effective_gid(), "", mode, now,
0U, 0U, 0U, "", get_effective_uid(), now); 0U, 0U, 0U, "", get_effective_uid(), now);
@ -647,20 +680,21 @@ void fuse_drive::notify_fuse_main_exit(int &ret) {
auto fuse_drive::open_impl(std::string api_path, auto fuse_drive::open_impl(std::string api_path,
struct fuse_file_info *file_info) -> api_error { struct fuse_file_info *file_info) -> api_error {
file_info->flags &= (~O_CREAT); file_info->flags &= (~O_CREAT);
return create_impl(api_path, 0, file_info); return create_impl(api_path, 0, file_info);
} }
auto fuse_drive::opendir_impl(std::string api_path, auto fuse_drive::opendir_impl(std::string api_path,
struct fuse_file_info *file_info) -> api_error { struct fuse_file_info *file_info) -> api_error {
const auto mask = auto mask = (O_RDONLY != (file_info->flags & O_ACCMODE) ? W_OK : R_OK) | X_OK;
(O_RDONLY != (file_info->flags & O_ACCMODE) ? W_OK : R_OK) | X_OK;
auto res = check_access(api_path, mask); auto res = check_access(api_path, mask);
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
if ((res = check_parent_access(api_path, mask)) != api_error::success) { res = check_parent_access(api_path, mask);
if (res != api_error::success) {
return res; return res;
} }
@ -673,9 +707,14 @@ auto fuse_drive::opendir_impl(std::string api_path,
return api_error::directory_not_found; return api_error::directory_not_found;
} }
if ((file_info->flags & O_APPEND) == O_APPEND ||
(file_info->flags & O_EXCL) == O_EXCL) {
return api_error::directory_exists;
}
directory_item_list list{}; directory_item_list list{};
if ((res = provider_.get_directory_items(api_path, list)) != res = provider_.get_directory_items(api_path, list);
api_error::success) { if (res != api_error::success) {
return res; return res;
} }
@ -703,7 +742,8 @@ auto fuse_drive::read_impl(std::string api_path, char *buffer, size_t read_size,
data_buffer data; data_buffer data;
res = res =
open_file->read(read_size, static_cast<std::uint64_t>(read_offset), data); open_file->read(read_size, static_cast<std::uint64_t>(read_offset), data);
if ((bytes_read = data.size()) != 0U) { bytes_read = data.size();
if (bytes_read != 0U) {
std::memcpy(buffer, data.data(), data.size()); std::memcpy(buffer, data.data(), data.size());
data.clear(); data.clear();
update_accessed_time(api_path); update_accessed_time(api_path);
@ -733,16 +773,17 @@ auto fuse_drive::readdir_impl(std::string api_path, void *buf,
} }
while (res == api_error::success) { while (res == api_error::success) {
res = (iter->fill_buffer( res =
static_cast<remote::file_offset>(offset++), fuse_fill_dir, buf, (iter->fill_buffer(
[this](const std::string &cur_api_path, static_cast<remote::file_offset>(offset++), fuse_fill_dir, buf,
std::uint64_t cur_file_size, const api_meta_map &meta, [this](const std::string &cur_api_path,
bool directory, struct stat *st) { std::uint64_t cur_file_size, const api_meta_map &meta,
fuse_drive_base::populate_stat(cur_api_path, cur_file_size, bool directory, struct stat *unix_st) {
meta, directory, provider_, st); fuse_drive_base::populate_stat(cur_api_path, cur_file_size, meta,
}) == 0) directory, provider_, unix_st);
? api_error::success }) == 0)
: api_error::os_error; ? api_error::success
: api_error::os_error;
} }
if ((res == api_error::os_error) && ((errno == 120) || (errno == ENOMEM))) { if ((res == api_error::os_error) && ((errno == 120) || (errno == ENOMEM))) {
@ -772,7 +813,7 @@ auto fuse_drive::releasedir_impl(
auto fuse_drive::rename_directory(const std::string &from_api_path, auto fuse_drive::rename_directory(const std::string &from_api_path,
const std::string &to_api_path) -> int { const std::string &to_api_path) -> int {
const auto res = fm_->rename_directory(from_api_path, to_api_path); auto res = fm_->rename_directory(from_api_path, to_api_path);
errno = std::abs(utils::from_api_error(res)); errno = std::abs(utils::from_api_error(res));
return (res == api_error::success) ? 0 : -1; return (res == api_error::success) ? 0 : -1;
} }
@ -780,7 +821,7 @@ auto fuse_drive::rename_directory(const std::string &from_api_path,
auto fuse_drive::rename_file(const std::string &from_api_path, auto fuse_drive::rename_file(const std::string &from_api_path,
const std::string &to_api_path, const std::string &to_api_path,
bool overwrite) -> int { bool overwrite) -> int {
const auto res = fm_->rename_file(from_api_path, to_api_path, overwrite); auto res = fm_->rename_file(from_api_path, to_api_path, overwrite);
errno = std::abs(utils::from_api_error(res)); errno = std::abs(utils::from_api_error(res));
return (res == api_error::success) ? 0 : -1; return (res == api_error::success) ? 0 : -1;
} }
@ -797,8 +838,8 @@ auto fuse_drive::rename_impl(std::string from_api_path,
return res; return res;
} }
if ((res = check_parent_access(from_api_path, W_OK | X_OK)) != res = check_parent_access(from_api_path, W_OK | X_OK);
api_error::success) { if (res != api_error::success) {
return res; return res;
} }
@ -825,7 +866,8 @@ auto fuse_drive::rmdir_impl(std::string api_path) -> api_error {
return res; return res;
} }
if ((res = provider_.remove_directory(api_path)) != api_error::success) { res = provider_.remove_directory(api_path);
if (res != api_error::success) {
return res; return res;
} }
@ -850,42 +892,48 @@ auto fuse_drive::getxattr_common(std::string api_path, const char *name,
return res; return res;
} }
if ((res = check_parent_access(api_path, X_OK)) != api_error::success) { res = check_parent_access(api_path, X_OK);
if (res != api_error::success) {
return res; return res;
} }
api_meta_map meta; api_meta_map meta;
auto found = false; auto found{false};
directory_cache_->execute_action( directory_cache_->execute_action(
utils::path::get_parent_api_path(api_path), utils::path::get_parent_api_path(api_path),
[&](directory_iterator &iterator) { [&](directory_iterator &iterator) {
directory_item dir_item{}; directory_item dir_item{};
if ((found = (iterator.get_directory_item(api_path, dir_item) == found = (iterator.get_directory_item(api_path, dir_item) ==
api_error::success))) { api_error::success);
if (found) {
meta = dir_item.meta; meta = dir_item.meta;
} }
}); });
if (found || res = found ? api_error::success : provider_.get_item_meta(api_path, meta);
((res = provider_.get_item_meta(api_path, meta)) == api_error::success)) { if (res != api_error::success) {
res = api_error::xattr_not_found; return res;
if (meta.find(attribute_name) != meta.end()) {
const auto data = macaron::Base64::Decode(meta[attribute_name]);
if ((position == nullptr) || (*position < data.size())) {
res = api_error::success;
attribute_size = static_cast<int>(data.size());
if (size != 0U) {
res = api_error::xattr_buffer_small;
if (size >= data.size()) {
memcpy(value, data.data(), data.size());
return api_error::success;
}
}
}
}
} }
return res; if (meta.find(attribute_name) == meta.end()) {
return api_error::xattr_not_found;
}
auto data = macaron::Base64::Decode(meta.at(attribute_name));
if ((position == nullptr) || (*position < data.size())) {
attribute_size = static_cast<int>(data.size());
if (size == 0U) {
return api_error::success;
}
if (size < data.size()) {
return api_error::xattr_buffer_small;
}
std::memcpy(value, data.data(), data.size());
}
return api_error::success;
} }
#if defined(__APPLE__) #if defined(__APPLE__)
@ -906,7 +954,7 @@ auto fuse_drive::getxattr_impl(std::string api_path, const char *name,
auto fuse_drive::listxattr_impl(std::string api_path, char *buffer, size_t size, auto fuse_drive::listxattr_impl(std::string api_path, char *buffer, size_t size,
int &required_size, int &required_size,
bool &return_size) -> api_error { bool &return_size) -> api_error {
const auto check_size = (size == 0); auto check_size = (size == 0);
auto res = check_parent_access(api_path, X_OK); auto res = check_parent_access(api_path, X_OK);
if (res != api_error::success) { if (res != api_error::success) {
@ -914,14 +962,15 @@ auto fuse_drive::listxattr_impl(std::string api_path, char *buffer, size_t size,
} }
api_meta_map meta; api_meta_map meta;
if ((res = provider_.get_item_meta(api_path, meta)) == api_error::success) { res = provider_.get_item_meta(api_path, meta);
if (res == api_error::success) {
for (auto &&meta_item : meta) { for (auto &&meta_item : meta) {
if (utils::collection::excludes(META_USED_NAMES, meta_item.first)) { if (utils::collection::excludes(META_USED_NAMES, meta_item.first)) {
auto attribute_name = meta_item.first; auto attribute_name = meta_item.first;
#if defined(__APPLE__) #if defined(__APPLE__)
if (attribute_name != G_KAUTH_FILESEC_XATTR) { if (attribute_name != G_KAUTH_FILESEC_XATTR) {
#endif #endif
const auto attribute_name_size = strlen(attribute_name.c_str()) + 1U; auto attribute_name_size = strlen(attribute_name.c_str()) + 1U;
if (size >= attribute_name_size) { if (size >= attribute_name_size) {
std::memcpy(&buffer[required_size], attribute_name.data(), std::memcpy(&buffer[required_size], attribute_name.data(),
attribute_name_size); attribute_name_size);
@ -988,7 +1037,7 @@ auto fuse_drive::setxattr_impl(std::string api_path, const char *name,
return res; return res;
} }
const auto attribute_namespace = auto attribute_namespace =
utils::string::contains(attribute_name, ".") utils::string::contains(attribute_name, ".")
? utils::string::split(attribute_name, '.', false)[0U] ? utils::string::split(attribute_name, '.', false)[0U]
: ""; : "";
@ -1007,15 +1056,18 @@ auto fuse_drive::setxattr_impl(std::string api_path, const char *name,
} }
api_meta_map meta; api_meta_map meta;
if ((res = provider_.get_item_meta(api_path, meta)) != api_error::success) { res = provider_.get_item_meta(api_path, meta);
if (res != api_error::success) {
return res; return res;
} }
if ((res = check_parent_access(api_path, X_OK)) != api_error::success) { res = check_parent_access(api_path, X_OK);
if (res != api_error::success) {
return res; return res;
} }
if ((res = check_owner(meta)) != api_error::success) { res = check_owner(meta);
if (res != api_error::success) {
return res; return res;
} }
@ -1039,9 +1091,7 @@ auto fuse_drive::setxattr_impl(std::string api_path, const char *name,
void fuse_drive::set_item_meta(const std::string &api_path, void fuse_drive::set_item_meta(const std::string &api_path,
const std::string &key, const std::string &key,
const std::string &value) { const std::string &value) {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
auto res = provider_.set_item_meta(api_path, key, value); auto res = provider_.set_item_meta(api_path, key, value);
if (res != api_error::success) { if (res != api_error::success) {
@ -1155,8 +1205,8 @@ auto fuse_drive::setbkuptime_impl(
std::string api_path, const struct timespec *bkuptime) -> api_error { std::string api_path, const struct timespec *bkuptime) -> api_error {
return check_and_perform( return check_and_perform(
api_path, X_OK, [&](api_meta_map &meta) -> api_error { api_path, X_OK, [&](api_meta_map &meta) -> api_error {
const auto nanos = bkuptime->tv_nsec + auto nanos = bkuptime->tv_nsec +
(bkuptime->tv_nsec * utils::time::NANOS_PER_SECOND); (bkuptime->tv_nsec * utils::time::NANOS_PER_SECOND);
return provider_.set_item_meta(api_path, META_BACKUP, return provider_.set_item_meta(api_path, META_BACKUP,
std::to_string(nanos)); std::to_string(nanos));
}); });
@ -1166,8 +1216,8 @@ auto fuse_drive::setchgtime_impl(std::string api_path,
const struct timespec *chgtime) -> api_error { const struct timespec *chgtime) -> api_error {
return check_and_perform( return check_and_perform(
api_path, X_OK, [&](api_meta_map &meta) -> api_error { api_path, X_OK, [&](api_meta_map &meta) -> api_error {
const auto nanos = chgtime->tv_nsec + auto nanos = chgtime->tv_nsec +
(chgtime->tv_nsec * utils::time::NANOS_PER_SECOND); (chgtime->tv_nsec * utils::time::NANOS_PER_SECOND);
return provider_.set_item_meta(api_path, META_CHANGED, return provider_.set_item_meta(api_path, META_CHANGED,
std::to_string(nanos)); std::to_string(nanos));
}); });
@ -1177,7 +1227,7 @@ auto fuse_drive::setcrtime_impl(std::string api_path,
const struct timespec *crtime) -> api_error { const struct timespec *crtime) -> api_error {
return check_and_perform( return check_and_perform(
api_path, X_OK, [&](api_meta_map &meta) -> api_error { api_path, X_OK, [&](api_meta_map &meta) -> api_error {
const auto nanos = auto nanos =
crtime->tv_nsec + (crtime->tv_nsec * utils::time::NANOS_PER_SECOND); crtime->tv_nsec + (crtime->tv_nsec * utils::time::NANOS_PER_SECOND);
return provider_.set_item_meta(api_path, META_CREATION, return provider_.set_item_meta(api_path, META_CREATION,
std::to_string(nanos)); std::to_string(nanos));
@ -1194,9 +1244,9 @@ auto fuse_drive::statfs_x_impl(std::string /*api_path*/,
return api_error::os_error; return api_error::os_error;
} }
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();
const auto used_blocks = utils::divide_with_ceiling( auto used_blocks = utils::divide_with_ceiling(
total_used, static_cast<std::uint64_t>(stbuf->f_bsize)); total_used, static_cast<std::uint64_t>(stbuf->f_bsize));
stbuf->f_blocks = utils::divide_with_ceiling( stbuf->f_blocks = utils::divide_with_ceiling(
total_bytes, static_cast<std::uint64_t>(stbuf->f_bsize)); total_bytes, static_cast<std::uint64_t>(stbuf->f_bsize));
@ -1220,10 +1270,9 @@ auto fuse_drive::statfs_impl(std::string /*api_path*/,
return api_error::os_error; return api_error::os_error;
} }
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();
const auto used_blocks = auto used_blocks = utils::divide_with_ceiling(total_used, stbuf->f_frsize);
utils::divide_with_ceiling(total_used, stbuf->f_frsize);
stbuf->f_files = 4294967295; stbuf->f_files = 4294967295;
stbuf->f_blocks = utils::divide_with_ceiling(total_bytes, stbuf->f_frsize); stbuf->f_blocks = utils::divide_with_ceiling(total_bytes, stbuf->f_frsize);
stbuf->f_bavail = stbuf->f_bfree = stbuf->f_bavail = stbuf->f_bfree =
@ -1248,12 +1297,12 @@ auto fuse_drive::truncate_impl(std::string api_path, off_t size) -> api_error {
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
res = check_parent_access(api_path, X_OK);
if ((res = check_parent_access(api_path, X_OK)) != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
res = check_access(api_path, W_OK);
if ((res = check_access(api_path, W_OK)) != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
@ -1261,11 +1310,15 @@ auto fuse_drive::truncate_impl(std::string api_path, off_t size) -> api_error {
{ {
open_file_data ofd{O_RDWR}; open_file_data ofd{O_RDWR};
std::shared_ptr<i_open_file> open_file; std::shared_ptr<i_open_file> open_file;
if ((res = fm_->open(api_path, false, ofd, handle, open_file)) != res = fm_->open(api_path, false, ofd, handle, open_file);
api_error::success) { if (res != api_error::success) {
return res; return res;
} }
if (not fm_->get_open_file(handle, true, open_file)) {
return api_error::invalid_handle;
}
res = open_file->resize(static_cast<std::uint64_t>(size)); res = open_file->resize(static_cast<std::uint64_t>(size));
} }
@ -1305,7 +1358,8 @@ auto fuse_drive::utimens_impl(std::string api_path,
return res; return res;
} }
if ((res = check_owner(meta)) != api_error::success) { res = check_owner(meta);
if (res != api_error::success) {
return res; return res;
} }
@ -1368,9 +1422,7 @@ auto fuse_drive::write_impl(std::string /*api_path*/
} }
void fuse_drive::update_accessed_time(const std::string &api_path) { void fuse_drive::update_accessed_time(const std::string &api_path) {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
if (atime_enabled_) { if (atime_enabled_) {
auto res = provider_.set_item_meta( auto res = provider_.set_item_meta(

View File

@ -23,6 +23,7 @@
#include "drives/fuse/fuse_drive_base.hpp" #include "drives/fuse/fuse_drive_base.hpp"
#include "events/events.hpp"
#include "platform/platform.hpp" #include "platform/platform.hpp"
#include "providers/i_provider.hpp" #include "providers/i_provider.hpp"
#include "utils/common.hpp" #include "utils/common.hpp"
@ -35,8 +36,10 @@ auto fuse_drive_base::access_impl(std::string api_path, int mask) -> api_error {
auto fuse_drive_base::check_access(const std::string &api_path, auto fuse_drive_base::check_access(const std::string &api_path,
int mask) const -> api_error { int mask) const -> api_error {
REPERTORY_USES_FUNCTION_NAME();
api_meta_map meta; api_meta_map meta;
const auto res = get_item_meta(api_path, meta); auto res = get_item_meta(api_path, meta);
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
@ -48,7 +51,7 @@ auto fuse_drive_base::check_access(const std::string &api_path,
} }
// Always allow forced user // Always allow forced user
if (forced_uid_.has_value() || (current_uid == get_effective_uid())) { if (forced_uid_.has_value() && (current_uid == get_effective_uid())) {
return api_error::success; return api_error::success;
} }
@ -57,9 +60,9 @@ auto fuse_drive_base::check_access(const std::string &api_path,
return api_error::success; return api_error::success;
} }
const auto effective_uid = auto effective_uid =
(forced_uid_.has_value() ? forced_uid_.value() : get_uid_from_meta(meta)); (forced_uid_.has_value() ? forced_uid_.value() : get_uid_from_meta(meta));
const auto effective_gid = auto effective_gid =
(forced_gid_.has_value() ? forced_gid_.value() : get_gid_from_meta(meta)); (forced_gid_.has_value() ? forced_gid_.value() : get_gid_from_meta(meta));
// Create file mode // Create file mode
@ -73,10 +76,9 @@ auto fuse_drive_base::check_access(const std::string &api_path,
if (current_uid == effective_uid) { if (current_uid == effective_uid) {
active_mask |= S_IRWXU; active_mask |= S_IRWXU;
} }
if (get_current_gid() == effective_gid) {
active_mask |= S_IRWXG; if (get_current_gid() == effective_gid ||
} utils::is_uid_member_of_group(current_uid, effective_gid)) {
if (utils::is_uid_member_of_group(current_uid, effective_gid)) {
active_mask |= S_IRWXG; active_mask |= S_IRWXG;
} }
@ -86,7 +88,7 @@ auto fuse_drive_base::check_access(const std::string &api_path,
// Check allow execute // Check allow execute
if ((mask & X_OK) == X_OK) { if ((mask & X_OK) == X_OK) {
if ((effective_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) { if ((effective_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) {
return api_error::permission_denied; return api_error::access_denied;
} }
} }
@ -174,8 +176,8 @@ auto fuse_drive_base::check_parent_access(const std::string &api_path,
for (auto parent = utils::path::get_parent_path(api_path); for (auto parent = utils::path::get_parent_path(api_path);
(ret == api_error::success) && not parent.empty(); (ret == api_error::success) && not parent.empty();
parent = utils::path::get_parent_path(parent)) { parent = utils::path::get_parent_path(parent)) {
if (((ret = check_access(parent, X_OK)) == api_error::success) && ret = check_access(parent, X_OK);
(parent == "/")) { if ((ret == api_error::success) && (parent == "/")) {
break; break;
} }
} }
@ -194,7 +196,7 @@ auto fuse_drive_base::check_parent_access(const std::string &api_path,
auto fuse_drive_base::check_readable(int flags, auto fuse_drive_base::check_readable(int flags,
const api_error &fail_error) -> api_error { const api_error &fail_error) -> api_error {
const auto mode = (flags & O_ACCMODE); auto mode = (flags & O_ACCMODE);
return ((mode == O_WRONLY) ? fail_error : api_error::success); return ((mode == O_WRONLY) ? fail_error : api_error::success);
} }
@ -320,9 +322,9 @@ void fuse_drive_base::populate_stat(const std::string &api_path,
st->st_size = static_cast<off_t>(size_or_count); st->st_size = static_cast<off_t>(size_or_count);
static const auto block_size_stat = static_cast<std::uint64_t>(512U); static const auto block_size_stat = static_cast<std::uint64_t>(512U);
static const auto block_size = static_cast<std::uint64_t>(4096U); static const auto block_size = static_cast<std::uint64_t>(4096U);
const auto size = utils::divide_with_ceiling( auto size = utils::divide_with_ceiling(
static_cast<std::uint64_t>(st->st_size), block_size) * static_cast<std::uint64_t>(st->st_size), block_size) *
block_size; block_size;
st->st_blocks = static_cast<blkcnt_t>( st->st_blocks = static_cast<blkcnt_t>(
std::max(block_size / block_size_stat, std::max(block_size / block_size_stat,
utils::divide_with_ceiling(size, block_size_stat))); utils::divide_with_ceiling(size, block_size_stat)));

View File

@ -27,18 +27,11 @@
namespace repertory::remote_fuse { namespace repertory::remote_fuse {
remote_client::remote_client(const app_config &config) remote_client::remote_client(const app_config &config)
: config_(config), : config_(config), packet_client_(config.get_remote_config()) {}
packet_client_(
config.get_remote_host_name_or_ip(),
config.get_remote_max_connections(), config.get_remote_port(),
config.get_remote_receive_timeout_secs(),
config.get_remote_send_timeout_secs(), config.get_remote_token()) {}
auto remote_client::fuse_access(const char *path, const std::int32_t &mask) auto remote_client::fuse_access(const char *path, const std::int32_t &mask)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -48,11 +41,9 @@ auto remote_client::fuse_access(const char *path, const std::int32_t &mask)
return packet_client_.send(function_name, request, service_flags); return packet_client_.send(function_name, request, service_flags);
} }
auto remote_client::fuse_chflags(const char *path, auto remote_client::fuse_chflags(const char *path, std::uint32_t flags)
std::uint32_t flags) -> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -64,9 +55,7 @@ auto remote_client::fuse_chflags(const char *path,
auto remote_client::fuse_chmod(const char *path, const remote::file_mode &mode) auto remote_client::fuse_chmod(const char *path, const remote::file_mode &mode)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -79,9 +68,7 @@ auto remote_client::fuse_chmod(const char *path, const remote::file_mode &mode)
auto remote_client::fuse_chown(const char *path, const remote::user_id &uid, auto remote_client::fuse_chown(const char *path, const remote::user_id &uid,
const remote::group_id &gid) const remote::group_id &gid)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -93,9 +80,7 @@ auto remote_client::fuse_chown(const char *path, const remote::user_id &uid,
} }
auto remote_client::fuse_destroy() -> packet::error_type { auto remote_client::fuse_destroy() -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
std::uint32_t service_flags{}; std::uint32_t service_flags{};
return packet_client_.send(function_name, service_flags); return packet_client_.send(function_name, service_flags);
@ -114,12 +99,11 @@ std::int32_t &mode, const remote::file_offset &offset, const remote::file_offset
return packetClient_.send(function_name, request, service_flags); return packetClient_.send(function_name, request, service_flags);
}*/ }*/
auto remote_client::fuse_fgetattr( auto remote_client::fuse_fgetattr(const char *path, remote::stat &st,
const char *path, remote::stat &st, bool &directory, bool &directory,
const remote::file_handle &handle) -> packet::error_type { const remote::file_handle &handle)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -143,12 +127,11 @@ auto remote_client::fuse_fgetattr(
return ret; return ret;
} }
auto remote_client::fuse_fsetattr_x( auto remote_client::fuse_fsetattr_x(const char *path,
const char *path, const remote::setattr_x &attr, const remote::setattr_x &attr,
const remote::file_handle &handle) -> packet::error_type { const remote::file_handle &handle)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -162,9 +145,7 @@ auto remote_client::fuse_fsetattr_x(
auto remote_client::fuse_fsync(const char *path, const std::int32_t &datasync, auto remote_client::fuse_fsync(const char *path, const std::int32_t &datasync,
const remote::file_handle &handle) const remote::file_handle &handle)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -175,12 +156,11 @@ auto remote_client::fuse_fsync(const char *path, const std::int32_t &datasync,
return packet_client_.send(function_name, request, service_flags); return packet_client_.send(function_name, request, service_flags);
} }
auto remote_client::fuse_ftruncate( auto remote_client::fuse_ftruncate(const char *path,
const char *path, const remote::file_offset &size, const remote::file_offset &size,
const remote::file_handle &handle) -> packet::error_type { const remote::file_handle &handle)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -193,9 +173,7 @@ auto remote_client::fuse_ftruncate(
auto remote_client::fuse_getattr(const char *path, remote::stat &st, auto remote_client::fuse_getattr(const char *path, remote::stat &st,
bool &directory) -> packet::error_type { bool &directory) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -262,12 +240,11 @@ response.CurrentPointer(), static_cast<std::size_t>(size2));
return ret; return ret;
}*/ }*/
auto remote_client::fuse_getxtimes( auto remote_client::fuse_getxtimes(const char *path,
const char *path, remote::file_time &bkuptime, remote::file_time &bkuptime,
remote::file_time &crtime) -> packet::error_type { remote::file_time &crtime)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -285,9 +262,7 @@ auto remote_client::fuse_getxtimes(
} }
auto remote_client::fuse_init() -> packet::error_type { auto remote_client::fuse_init() -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
std::uint32_t service_flags{}; std::uint32_t service_flags{};
return packet_client_.send(function_name, service_flags); return packet_client_.send(function_name, service_flags);
@ -316,9 +291,7 @@ static_cast<std::size_t>(size2));
auto remote_client::fuse_mkdir(const char *path, const remote::file_mode &mode) auto remote_client::fuse_mkdir(const char *path, const remote::file_mode &mode)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -330,9 +303,7 @@ auto remote_client::fuse_mkdir(const char *path, const remote::file_mode &mode)
auto remote_client::fuse_opendir(const char *path, remote::file_handle &handle) auto remote_client::fuse_opendir(const char *path, remote::file_handle &handle)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -352,9 +323,7 @@ auto remote_client::fuse_create(const char *path, const remote::file_mode &mode,
const remote::open_flags &flags, const remote::open_flags &flags,
remote::file_handle &handle) remote::file_handle &handle)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -375,9 +344,7 @@ auto remote_client::fuse_create(const char *path, const remote::file_mode &mode,
auto remote_client::fuse_open(const char *path, const remote::open_flags &flags, auto remote_client::fuse_open(const char *path, const remote::open_flags &flags,
remote::file_handle &handle) remote::file_handle &handle)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -394,13 +361,12 @@ auto remote_client::fuse_open(const char *path, const remote::open_flags &flags,
return ret; return ret;
} }
auto remote_client::fuse_read( auto remote_client::fuse_read(const char *path, char *buffer,
const char *path, char *buffer, const remote::file_size &read_size, const remote::file_size &read_size,
const remote::file_offset &read_offset, const remote::file_offset &read_offset,
const remote::file_handle &handle) -> packet::error_type { const remote::file_handle &handle)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -419,11 +385,9 @@ auto remote_client::fuse_read(
return ret; return ret;
} }
auto remote_client::fuse_rename(const char *from, auto remote_client::fuse_rename(const char *from, const char *to)
const char *to) -> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(from); request.encode(from);
@ -433,13 +397,12 @@ auto remote_client::fuse_rename(const char *from,
return packet_client_.send(function_name, request, service_flags); return packet_client_.send(function_name, request, service_flags);
} }
auto remote_client::fuse_write( auto remote_client::fuse_write(const char *path, const char *buffer,
const char *path, const char *buffer, const remote::file_size &write_size, const remote::file_size &write_size,
const remote::file_offset &write_offset, const remote::file_offset &write_offset,
const remote::file_handle &handle) -> packet::error_type { const remote::file_handle &handle)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
if (write_size > std::numeric_limits<std::size_t>::max()) { if (write_size > std::numeric_limits<std::size_t>::max()) {
return -ERANGE; return -ERANGE;
@ -456,13 +419,12 @@ auto remote_client::fuse_write(
return packet_client_.send(function_name, request, service_flags); return packet_client_.send(function_name, request, service_flags);
} }
auto remote_client::fuse_write_base64( auto remote_client::fuse_write_base64(const char *path, const char *buffer,
const char *path, const char *buffer, const remote::file_size &write_size, const remote::file_size &write_size,
const remote::file_offset &write_offset, const remote::file_offset &write_offset,
const remote::file_handle &handle) -> packet::error_type { const remote::file_handle &handle)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
if (write_size > std::numeric_limits<std::size_t>::max()) { if (write_size > std::numeric_limits<std::size_t>::max()) {
return -ERANGE; return -ERANGE;
@ -483,9 +445,7 @@ auto remote_client::fuse_readdir(const char *path,
const remote::file_offset &offset, const remote::file_offset &offset,
const remote::file_handle &handle, const remote::file_handle &handle,
std::string &item_path) -> packet::error_type { std::string &item_path) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -503,11 +463,10 @@ auto remote_client::fuse_readdir(const char *path,
return ret; return ret;
} }
auto remote_client::fuse_release( auto remote_client::fuse_release(const char *path,
const char *path, const remote::file_handle &handle) -> packet::error_type { const remote::file_handle &handle)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -517,11 +476,10 @@ auto remote_client::fuse_release(
return packet_client_.send(function_name, request, service_flags); return packet_client_.send(function_name, request, service_flags);
} }
auto remote_client::fuse_releasedir( auto remote_client::fuse_releasedir(const char *path,
const char *path, const remote::file_handle &handle) -> packet::error_type { const remote::file_handle &handle)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -540,9 +498,7 @@ request.Encode(name);
}*/ }*/
auto remote_client::fuse_rmdir(const char *path) -> packet::error_type { auto remote_client::fuse_rmdir(const char *path) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -553,9 +509,7 @@ auto remote_client::fuse_rmdir(const char *path) -> packet::error_type {
auto remote_client::fuse_setattr_x(const char *path, remote::setattr_x &attr) auto remote_client::fuse_setattr_x(const char *path, remote::setattr_x &attr)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -565,11 +519,10 @@ auto remote_client::fuse_setattr_x(const char *path, remote::setattr_x &attr)
return packet_client_.send(function_name, request, service_flags); return packet_client_.send(function_name, request, service_flags);
} }
auto remote_client::fuse_setbkuptime( auto remote_client::fuse_setbkuptime(const char *path,
const char *path, const remote::file_time &bkuptime) -> packet::error_type { const remote::file_time &bkuptime)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -579,11 +532,10 @@ auto remote_client::fuse_setbkuptime(
return packet_client_.send(function_name, request, service_flags); return packet_client_.send(function_name, request, service_flags);
} }
auto remote_client::fuse_setchgtime( auto remote_client::fuse_setchgtime(const char *path,
const char *path, const remote::file_time &chgtime) -> packet::error_type { const remote::file_time &chgtime)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -593,11 +545,10 @@ auto remote_client::fuse_setchgtime(
return packet_client_.send(function_name, request, service_flags); return packet_client_.send(function_name, request, service_flags);
} }
auto remote_client::fuse_setcrtime( auto remote_client::fuse_setcrtime(const char *path,
const char *path, const remote::file_time &crtime) -> packet::error_type { const remote::file_time &crtime)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -608,9 +559,7 @@ auto remote_client::fuse_setcrtime(
} }
auto remote_client::fuse_setvolname(const char *volname) -> packet::error_type { auto remote_client::fuse_setvolname(const char *volname) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(volname); request.encode(volname);
@ -651,9 +600,7 @@ request.encode(flags); request.encode(position);
auto remote_client::fuse_statfs(const char *path, std::uint64_t frsize, auto remote_client::fuse_statfs(const char *path, std::uint64_t frsize,
remote::statfs &st) -> packet::error_type { remote::statfs &st) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -672,9 +619,7 @@ auto remote_client::fuse_statfs(const char *path, std::uint64_t frsize,
auto remote_client::fuse_statfs_x(const char *path, std::uint64_t bsize, auto remote_client::fuse_statfs_x(const char *path, std::uint64_t bsize,
remote::statfs_x &st) -> packet::error_type { remote::statfs_x &st) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -691,11 +636,10 @@ auto remote_client::fuse_statfs_x(const char *path, std::uint64_t bsize,
return ret; return ret;
} }
auto remote_client::fuse_truncate( auto remote_client::fuse_truncate(const char *path,
const char *path, const remote::file_offset &size) -> packet::error_type { const remote::file_offset &size)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -706,9 +650,7 @@ auto remote_client::fuse_truncate(
} }
auto remote_client::fuse_unlink(const char *path) -> packet::error_type { auto remote_client::fuse_unlink(const char *path) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -718,11 +660,9 @@ auto remote_client::fuse_unlink(const char *path) -> packet::error_type {
} }
auto remote_client::fuse_utimens(const char *path, const remote::file_time *tv, auto remote_client::fuse_utimens(const char *path, const remote::file_time *tv,
std::uint64_t op0, std::uint64_t op0, std::uint64_t op1)
std::uint64_t op1) -> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -734,11 +674,10 @@ auto remote_client::fuse_utimens(const char *path, const remote::file_time *tv,
return packet_client_.send(function_name, request, service_flags); return packet_client_.send(function_name, request, service_flags);
} }
auto remote_client::json_create_directory_snapshot( auto remote_client::json_create_directory_snapshot(const std::string &path,
const std::string &path, json &json_data) -> packet::error_type { json &json_data)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -757,9 +696,7 @@ auto remote_client::json_create_directory_snapshot(
auto remote_client::json_read_directory_snapshot( auto remote_client::json_read_directory_snapshot(
const std::string &path, const remote::file_handle &handle, const std::string &path, const remote::file_handle &handle,
std::uint32_t page, json &json_data) -> packet::error_type { std::uint32_t page, json &json_data) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -778,11 +715,9 @@ auto remote_client::json_read_directory_snapshot(
} }
auto remote_client::json_release_directory_snapshot( auto remote_client::json_release_directory_snapshot(
const std::string &path, const std::string &path, const remote::file_handle &handle)
const remote::file_handle &handle) -> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);

View File

@ -88,9 +88,7 @@ auto remote_fuse_drive::create_impl(std::string api_path, mode_t mode,
} }
void remote_fuse_drive::destroy_impl(void *ptr) { void remote_fuse_drive::destroy_impl(void *ptr) {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
event_system::instance().raise<drive_unmount_pending>(get_mount_location()); event_system::instance().raise<drive_unmount_pending>(get_mount_location());
@ -227,9 +225,7 @@ auto remote_fuse_drive::init_impl(struct fuse_conn_info *conn,
#else #else
auto remote_fuse_drive::init_impl(struct fuse_conn_info *conn) -> void * { auto remote_fuse_drive::init_impl(struct fuse_conn_info *conn) -> void * {
#endif #endif
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
auto *ret = fuse_base::init_impl(conn, cfg); auto *ret = fuse_base::init_impl(conn, cfg);
@ -292,6 +288,10 @@ auto remote_fuse_drive::open_impl(std::string api_path,
auto remote_fuse_drive::opendir_impl( auto remote_fuse_drive::opendir_impl(
std::string api_path, struct fuse_file_info *f_info) -> api_error { std::string api_path, struct fuse_file_info *f_info) -> api_error {
if ((f_info->flags & O_APPEND) == O_APPEND ||
(f_info->flags & O_EXCL) == O_EXCL) {
return api_error::directory_exists;
}
return utils::to_api_error( return utils::to_api_error(
remote_instance_->fuse_opendir(api_path.c_str(), f_info->fh)); remote_instance_->fuse_opendir(api_path.c_str(), f_info->fh));

View File

@ -96,7 +96,7 @@ auto remote_server::populate_file_info(const std::string &api_path,
meta_attributes = meta_attributes =
utils::file::directory(construct_path(api_path)).exists() utils::file::directory(construct_path(api_path)).exists()
? std::to_string(FILE_ATTRIBUTE_DIRECTORY) ? std::to_string(FILE_ATTRIBUTE_DIRECTORY)
: std::to_string(FILE_ATTRIBUTE_NORMAL); : std::to_string(FILE_ATTRIBUTE_ARCHIVE);
drive_.set_item_meta(api_path, META_ATTRIBUTES, meta_attributes); drive_.set_item_meta(api_path, META_ATTRIBUTES, meta_attributes);
} }
const auto attributes = utils::string::to_uint32(meta_attributes); const auto attributes = utils::string::to_uint32(meta_attributes);
@ -112,9 +112,7 @@ void remote_server::populate_file_info(const std::string &api_path,
const UINT64 &file_size, const UINT64 &file_size,
const UINT32 &attributes, const UINT32 &attributes,
remote::file_info &file_info) { remote::file_info &file_info) {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
api_meta_map meta{}; api_meta_map meta{};
const auto res = drive_.get_item_meta(api_path, meta); const auto res = drive_.get_item_meta(api_path, meta);
@ -199,11 +197,11 @@ void remote_server::populate_stat(const struct stat64 &unix_st,
auto remote_server::fuse_access(const char *path, const std::int32_t &mask) auto remote_server::fuse_access(const char *path, const std::int32_t &mask)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto api_path = utils::path::create_api_path(path);
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
const auto res = access(file_path.c_str(), mask); const auto res = access(file_path.c_str(), mask);
auto ret = ((res < 0) ? -errno : 0); auto ret = ((res < 0) ? -errno : 0);
RAISE_REMOTE_FUSE_SERVER_EVENT(function_name, file_path, ret); RAISE_REMOTE_FUSE_SERVER_EVENT(function_name, file_path, ret);
@ -212,9 +210,7 @@ auto remote_server::fuse_access(const char *path, const std::int32_t &mask)
auto remote_server::fuse_chflags(const char *path, auto remote_server::fuse_chflags(const char *path,
std::uint32_t flags) -> packet::error_type { std::uint32_t flags) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto api_path = utils::path::create_api_path(path); const auto api_path = utils::path::create_api_path(path);
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
@ -234,9 +230,7 @@ auto remote_server::fuse_chflags(const char *path,
auto remote_server::fuse_chmod(const char *path, const remote::file_mode &mode) auto remote_server::fuse_chmod(const char *path, const remote::file_mode &mode)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
const auto res = chmod(file_path.c_str(), mode); const auto res = chmod(file_path.c_str(), mode);
@ -248,9 +242,7 @@ auto remote_server::fuse_chmod(const char *path, const remote::file_mode &mode)
auto remote_server::fuse_chown(const char *path, const remote::user_id &uid, auto remote_server::fuse_chown(const char *path, const remote::user_id &uid,
const remote::group_id &gid) const remote::group_id &gid)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
const auto res = chown(file_path.c_str(), uid, gid); const auto res = chown(file_path.c_str(), uid, gid);
@ -263,9 +255,7 @@ auto remote_server::fuse_create(const char *path, const remote::file_mode &mode,
const remote::open_flags &flags, const remote::open_flags &flags,
remote::file_handle &handle) remote::file_handle &handle)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
const auto res = const auto res =
@ -273,7 +263,12 @@ auto remote_server::fuse_create(const char *path, const remote::file_mode &mode,
static_cast<int>(remote::create_os_open_flags(flags)), mode); static_cast<int>(remote::create_os_open_flags(flags)), mode);
if (res >= 0) { if (res >= 0) {
handle = static_cast<remote::file_handle>(res); handle = static_cast<remote::file_handle>(res);
set_open_info(res, open_info{0, "", nullptr, file_path}); set_open_info(res, open_info{
"",
nullptr,
{},
file_path,
});
} }
auto ret = ((res < 0) ? -errno : 0); auto ret = ((res < 0) ? -errno : 0);
@ -282,9 +277,7 @@ auto remote_server::fuse_create(const char *path, const remote::file_mode &mode,
} }
auto remote_server::fuse_destroy() -> packet::error_type { auto remote_server::fuse_destroy() -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
RAISE_REMOTE_FUSE_SERVER_EVENT(function_name, "", 0); RAISE_REMOTE_FUSE_SERVER_EVENT(function_name, "", 0);
return 0; return 0;
@ -331,9 +324,7 @@ length); ret = ((res < 0) ? -errno : 0); #endif
auto remote_server::fuse_fgetattr( auto remote_server::fuse_fgetattr(
const char *path, remote::stat &r_stat, bool &directory, const char *path, remote::stat &r_stat, bool &directory,
const remote::file_handle &handle) -> packet::error_type { const remote::file_handle &handle) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
r_stat = {}; r_stat = {};
@ -357,9 +348,7 @@ auto remote_server::fuse_fgetattr(
auto remote_server::fuse_fsetattr_x( auto remote_server::fuse_fsetattr_x(
const char *path, const remote::setattr_x &attr, const char *path, const remote::setattr_x &attr,
const remote::file_handle &handle) -> packet::error_type { const remote::file_handle &handle) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto api_path = utils::path::create_api_path(path); const auto api_path = utils::path::create_api_path(path);
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
@ -454,9 +443,7 @@ auto remote_server::fuse_fsetattr_x(
auto remote_server::fuse_fsync(const char *path, const std::int32_t &datasync, auto remote_server::fuse_fsync(const char *path, const std::int32_t &datasync,
const remote::file_handle &handle) const remote::file_handle &handle)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
@ -479,9 +466,7 @@ auto remote_server::fuse_fsync(const char *path, const std::int32_t &datasync,
auto remote_server::fuse_ftruncate( auto remote_server::fuse_ftruncate(
const char *path, const remote::file_offset &size, const char *path, const remote::file_offset &size,
const remote::file_handle &handle) -> packet::error_type { const remote::file_handle &handle) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
@ -498,9 +483,7 @@ auto remote_server::fuse_ftruncate(
auto remote_server::fuse_getattr(const char *path, remote::stat &r_stat, auto remote_server::fuse_getattr(const char *path, remote::stat &r_stat,
bool &directory) -> packet::error_type { bool &directory) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto api_path = utils::path::create_api_path(path); const auto api_path = utils::path::create_api_path(path);
const auto file_path = construct_path(api_path); const auto file_path = construct_path(api_path);
@ -578,9 +561,7 @@ file_path, ret); return ret;
auto remote_server::fuse_getxtimes( auto remote_server::fuse_getxtimes(
const char *path, remote::file_time &bkuptime, const char *path, remote::file_time &bkuptime,
remote::file_time &crtime) -> packet::error_type { remote::file_time &crtime) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto api_path = utils::path::create_api_path(path); const auto api_path = utils::path::create_api_path(path);
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
@ -610,9 +591,7 @@ auto remote_server::fuse_getxtimes(
} }
auto remote_server::fuse_init() -> packet::error_type { auto remote_server::fuse_init() -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
RAISE_REMOTE_FUSE_SERVER_EVENT(function_name, "", 0); RAISE_REMOTE_FUSE_SERVER_EVENT(function_name, "", 0);
return 0; return 0;
@ -630,9 +609,7 @@ auto res = listxattr(file_path.c_str(), buffer, size); #endif auto ret = ((res <
auto remote_server::fuse_mkdir(const char *path, const remote::file_mode &mode) auto remote_server::fuse_mkdir(const char *path, const remote::file_mode &mode)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
const auto res = mkdir(file_path.c_str(), mode); const auto res = mkdir(file_path.c_str(), mode);
@ -644,16 +621,19 @@ auto remote_server::fuse_mkdir(const char *path, const remote::file_mode &mode)
auto remote_server::fuse_open(const char *path, const remote::open_flags &flags, auto remote_server::fuse_open(const char *path, const remote::open_flags &flags,
remote::file_handle &handle) remote::file_handle &handle)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
const auto res = open(file_path.c_str(), const auto res = open(file_path.c_str(),
static_cast<int>(remote::create_os_open_flags(flags))); static_cast<int>(remote::create_os_open_flags(flags)));
if (res >= 0) { if (res >= 0) {
handle = static_cast<remote::file_handle>(res); handle = static_cast<remote::file_handle>(res);
set_open_info(res, open_info{0, "", nullptr, file_path}); set_open_info(res, open_info{
"",
nullptr,
{},
file_path,
});
} }
auto ret = ((res < 0) ? -errno : 0); auto ret = ((res < 0) ? -errno : 0);
RAISE_REMOTE_FUSE_SERVER_EVENT(function_name, file_path, ret); RAISE_REMOTE_FUSE_SERVER_EVENT(function_name, file_path, ret);
@ -662,9 +642,7 @@ auto remote_server::fuse_open(const char *path, const remote::open_flags &flags,
auto remote_server::fuse_opendir(const char *path, remote::file_handle &handle) auto remote_server::fuse_opendir(const char *path, remote::file_handle &handle)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
@ -691,9 +669,7 @@ auto remote_server::fuse_read(
const char *path, char *buffer, const remote::file_size &read_size, const char *path, char *buffer, const remote::file_size &read_size,
const remote::file_offset &read_offset, const remote::file_offset &read_offset,
const remote::file_handle &handle) -> packet::error_type { const remote::file_handle &handle) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
auto &data = *reinterpret_cast<data_buffer *>(buffer); auto &data = *reinterpret_cast<data_buffer *>(buffer);
@ -715,9 +691,7 @@ auto remote_server::fuse_read(
auto remote_server::fuse_rename(const char *from, auto remote_server::fuse_rename(const char *from,
const char *to) -> packet::error_type { const char *to) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto from_path = utils::path::combine(mount_location_, {from}); const auto from_path = utils::path::combine(mount_location_, {from});
const auto to_path = utils::path::combine(mount_location_, {to}); const auto to_path = utils::path::combine(mount_location_, {to});
@ -732,9 +706,7 @@ auto remote_server::fuse_readdir(const char *path,
const remote::file_offset &offset, const remote::file_offset &offset,
const remote::file_handle &handle, const remote::file_handle &handle,
std::string &item_path) -> packet::error_type { std::string &item_path) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
auto res = 0; auto res = 0;
@ -758,9 +730,7 @@ auto remote_server::fuse_readdir(const char *path,
auto remote_server::fuse_release( auto remote_server::fuse_release(
const char *path, const remote::file_handle &handle) -> packet::error_type { const char *path, const remote::file_handle &handle) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet::error_type ret = 0; packet::error_type ret = 0;
@ -778,9 +748,7 @@ auto remote_server::fuse_release(
auto remote_server::fuse_releasedir( auto remote_server::fuse_releasedir(
const char *path, const remote::file_handle &handle) -> packet::error_type { const char *path, const remote::file_handle &handle) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
@ -801,9 +769,7 @@ removexattr(file_path.c_str(), name); #endif auto ret = ((res < 0) ? -errno :
}*/ }*/
auto remote_server::fuse_rmdir(const char *path) -> packet::error_type { auto remote_server::fuse_rmdir(const char *path) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
const auto res = rmdir(file_path.c_str()); const auto res = rmdir(file_path.c_str());
@ -823,9 +789,7 @@ auto remote_server::fuse_rmdir(const char *path) -> packet::error_type {
auto remote_server::fuse_setattr_x(const char *path, remote::setattr_x &attr) auto remote_server::fuse_setattr_x(const char *path, remote::setattr_x &attr)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
auto ret = fuse_fsetattr_x( auto ret = fuse_fsetattr_x(
@ -836,9 +800,7 @@ auto remote_server::fuse_setattr_x(const char *path, remote::setattr_x &attr)
auto remote_server::fuse_setbkuptime( auto remote_server::fuse_setbkuptime(
const char *path, const remote::file_time &bkuptime) -> packet::error_type { const char *path, const remote::file_time &bkuptime) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto api_path = utils::path::create_api_path(path); const auto api_path = utils::path::create_api_path(path);
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
@ -858,9 +820,7 @@ auto remote_server::fuse_setbkuptime(
auto remote_server::fuse_setchgtime( auto remote_server::fuse_setchgtime(
const char *path, const remote::file_time &chgtime) -> packet::error_type { const char *path, const remote::file_time &chgtime) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto api_path = utils::path::create_api_path(path); const auto api_path = utils::path::create_api_path(path);
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
@ -880,9 +840,7 @@ auto remote_server::fuse_setchgtime(
auto remote_server::fuse_setcrtime( auto remote_server::fuse_setcrtime(
const char *path, const remote::file_time &crtime) -> packet::error_type { const char *path, const remote::file_time &crtime) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto api_path = utils::path::create_api_path(path); const auto api_path = utils::path::create_api_path(path);
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
@ -901,9 +859,7 @@ auto remote_server::fuse_setcrtime(
} }
auto remote_server::fuse_setvolname(const char *volname) -> packet::error_type { auto remote_server::fuse_setvolname(const char *volname) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
RAISE_REMOTE_FUSE_SERVER_EVENT(function_name, volname, 0); RAISE_REMOTE_FUSE_SERVER_EVENT(function_name, volname, 0);
return 0; return 0;
@ -931,9 +887,7 @@ res = setxattr(file_path.c_str(), name, value, size, position, flags); auto ret
auto remote_server::fuse_statfs(const char *path, std::uint64_t frsize, auto remote_server::fuse_statfs(const char *path, std::uint64_t frsize,
remote::statfs &r_stat) -> packet::error_type { remote::statfs &r_stat) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
@ -954,9 +908,7 @@ auto remote_server::fuse_statfs(const char *path, std::uint64_t frsize,
auto remote_server::fuse_statfs_x(const char *path, std::uint64_t bsize, auto remote_server::fuse_statfs_x(const char *path, std::uint64_t bsize,
remote::statfs_x &r_stat) remote::statfs_x &r_stat)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
@ -980,9 +932,7 @@ auto remote_server::fuse_statfs_x(const char *path, std::uint64_t bsize,
auto remote_server::fuse_truncate( auto remote_server::fuse_truncate(
const char *path, const remote::file_offset &size) -> packet::error_type { const char *path, const remote::file_offset &size) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
const auto res = truncate(file_path.c_str(), static_cast<off_t>(size)); const auto res = truncate(file_path.c_str(), static_cast<off_t>(size));
@ -992,9 +942,7 @@ auto remote_server::fuse_truncate(
} }
auto remote_server::fuse_unlink(const char *path) -> packet::error_type { auto remote_server::fuse_unlink(const char *path) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
const auto res = unlink(file_path.c_str()); const auto res = unlink(file_path.c_str());
@ -1006,9 +954,7 @@ auto remote_server::fuse_unlink(const char *path) -> packet::error_type {
auto remote_server::fuse_utimens(const char *path, const remote::file_time *tv, auto remote_server::fuse_utimens(const char *path, const remote::file_time *tv,
std::uint64_t op0, std::uint64_t op0,
std::uint64_t op1) -> packet::error_type { std::uint64_t op1) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
@ -1038,9 +984,7 @@ auto remote_server::fuse_write(
const char *path, const char *buffer, const remote::file_size &write_size, const char *path, const char *buffer, const remote::file_size &write_size,
const remote::file_offset &write_offset, const remote::file_offset &write_offset,
const remote::file_handle &handle) -> packet::error_type { const remote::file_handle &handle) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
@ -1071,9 +1015,7 @@ auto remote_server::fuse_write_base64(
// WinFSP Layer // WinFSP Layer
auto remote_server::winfsp_can_delete(PVOID file_desc, auto remote_server::winfsp_can_delete(PVOID file_desc,
PWSTR file_name) -> packet::error_type { PWSTR file_name) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto relative_path = utils::string::to_utf8(file_name); const auto relative_path = utils::string::to_utf8(file_name);
const auto file_path = construct_path(relative_path); const auto file_path = construct_path(relative_path);
@ -1088,8 +1030,7 @@ auto remote_server::winfsp_can_delete(PVOID file_desc,
utils::path::create_api_path(relative_path)) utils::path::create_api_path(relative_path))
? STATUS_DIRECTORY_NOT_EMPTY ? STATUS_DIRECTORY_NOT_EMPTY
: STATUS_SUCCESS : STATUS_SUCCESS
: drive_.is_processing(utils::path::create_api_path(relative_path))
? STATUS_DEVICE_BUSY
: STATUS_SUCCESS); : STATUS_SUCCESS);
} }
@ -1099,19 +1040,17 @@ auto remote_server::winfsp_can_delete(PVOID file_desc,
auto remote_server::winfsp_cleanup(PVOID /*file_desc*/, PWSTR file_name, auto remote_server::winfsp_cleanup(PVOID /*file_desc*/, PWSTR file_name,
UINT32 flags, UINT32 flags,
BOOLEAN &was_closed) -> packet::error_type { BOOLEAN &was_deleted) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto relative_path = utils::string::to_utf8(file_name); const auto relative_path = utils::string::to_utf8(file_name);
const auto file_path = construct_path(relative_path); const auto file_path = construct_path(relative_path);
was_closed = 0; was_deleted = 0U;
const auto directory = utils::file::directory(file_path).exists(); const auto directory = utils::file::directory(file_path).exists();
if (flags & FileSystemBase::FspCleanupDelete) { if (flags & FileSystemBase::FspCleanupDelete) {
remove_all(file_path); remove_all(file_path);
was_closed = 1; was_deleted = 1U;
if (directory) { if (directory) {
rmdir(file_path.c_str()); rmdir(file_path.c_str());
@ -1159,9 +1098,7 @@ auto remote_server::winfsp_cleanup(PVOID /*file_desc*/, PWSTR file_name,
} }
auto remote_server::winfsp_close(PVOID file_desc) -> packet::error_type { auto remote_server::winfsp_close(PVOID file_desc) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
std::string file_path; std::string file_path;
const auto handle = reinterpret_cast<remote::file_handle>(file_desc); const auto handle = reinterpret_cast<remote::file_handle>(file_desc);
@ -1182,9 +1119,7 @@ auto remote_server::winfsp_create(PWSTR file_name, UINT32 create_options,
remote::file_info *file_info, remote::file_info *file_info,
std::string &normalized_name, std::string &normalized_name,
BOOLEAN &exists) -> packet::error_type { BOOLEAN &exists) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto relative_path = utils::string::to_utf8(file_name); const auto relative_path = utils::string::to_utf8(file_name);
const auto file_path = construct_path(relative_path); const auto file_path = construct_path(relative_path);
@ -1194,14 +1129,11 @@ auto remote_server::winfsp_create(PWSTR file_name, UINT32 create_options,
attributes |= FILE_ATTRIBUTE_DIRECTORY; attributes |= FILE_ATTRIBUTE_DIRECTORY;
} else { } else {
attributes &= static_cast<UINT32>(~FILE_ATTRIBUTE_DIRECTORY); attributes &= static_cast<UINT32>(~FILE_ATTRIBUTE_DIRECTORY);
attributes |= FILE_ATTRIBUTE_ARCHIVE;
} }
if (not attributes) { remote::file_mode mode{0U};
attributes = FILE_ATTRIBUTE_NORMAL; std::uint32_t flags{0U};
}
remote::file_mode mode = 0;
std::uint32_t flags = 0;
utils::windows_create_to_unix(create_options, granted_access, flags, mode); utils::windows_create_to_unix(create_options, granted_access, flags, mode);
int res = 0; int res = 0;
@ -1218,7 +1150,12 @@ auto remote_server::winfsp_create(PWSTR file_name, UINT32 create_options,
*file_desc = reinterpret_cast<PVOID>(res); *file_desc = reinterpret_cast<PVOID>(res);
drive_.set_item_meta(construct_api_path(file_path), META_ATTRIBUTES, drive_.set_item_meta(construct_api_path(file_path), META_ATTRIBUTES,
std::to_string(attributes)); std::to_string(attributes));
set_open_info(res, open_info{0, "", nullptr, file_path}); set_open_info(res, open_info{
"",
nullptr,
{},
file_path,
});
const auto api_path = utils::path::create_api_path(relative_path); const auto api_path = utils::path::create_api_path(relative_path);
normalized_name = utils::string::replace_copy(api_path, '/', '\\'); normalized_name = utils::string::replace_copy(api_path, '/', '\\');
@ -1233,9 +1170,7 @@ auto remote_server::winfsp_create(PWSTR file_name, UINT32 create_options,
auto remote_server::winfsp_flush(PVOID file_desc, remote::file_info *file_info) auto remote_server::winfsp_flush(PVOID file_desc, remote::file_info *file_info)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto handle = reinterpret_cast<remote::file_handle>(file_desc); const auto handle = reinterpret_cast<remote::file_handle>(file_desc);
auto ret = static_cast<packet::error_type>( auto ret = static_cast<packet::error_type>(
@ -1257,9 +1192,7 @@ auto remote_server::winfsp_flush(PVOID file_desc, remote::file_info *file_info)
auto remote_server::winfsp_get_file_info( auto remote_server::winfsp_get_file_info(
PVOID file_desc, remote::file_info *file_info) -> packet::error_type { PVOID file_desc, remote::file_info *file_info) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto handle = reinterpret_cast<remote::file_handle>(file_desc); const auto handle = reinterpret_cast<remote::file_handle>(file_desc);
auto ret = static_cast<packet::error_type>( auto ret = static_cast<packet::error_type>(
@ -1280,9 +1213,7 @@ auto remote_server::winfsp_get_security_by_name(
PWSTR file_name, PUINT32 attributes, PWSTR file_name, PUINT32 attributes,
std::uint64_t * /*security_descriptor_size*/, std::uint64_t * /*security_descriptor_size*/,
std::wstring & /*str_descriptor*/) -> packet::error_type { std::wstring & /*str_descriptor*/) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
auto ret = static_cast<packet::error_type>(STATUS_SUCCESS); auto ret = static_cast<packet::error_type>(STATUS_SUCCESS);
const auto file_path = construct_path(file_name); const auto file_path = construct_path(file_name);
@ -1306,9 +1237,7 @@ auto remote_server::winfsp_get_security_by_name(
auto remote_server::winfsp_get_volume_info( auto remote_server::winfsp_get_volume_info(
UINT64 &total_size, UINT64 &free_size, UINT64 &total_size, UINT64 &free_size,
std::string &volume_label) -> packet::error_type { std::string &volume_label) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
drive_.get_volume_info(total_size, free_size, volume_label); drive_.get_volume_info(total_size, free_size, volume_label);
RAISE_REMOTE_FUSE_SERVER_EVENT(function_name, volume_label, STATUS_SUCCESS); RAISE_REMOTE_FUSE_SERVER_EVENT(function_name, volume_label, STATUS_SUCCESS);
@ -1317,9 +1246,7 @@ auto remote_server::winfsp_get_volume_info(
auto remote_server::winfsp_mounted(const std::wstring &location) auto remote_server::winfsp_mounted(const std::wstring &location)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
RAISE_REMOTE_FUSE_SERVER_EVENT( RAISE_REMOTE_FUSE_SERVER_EVENT(
function_name, utils::string::to_utf8(location), STATUS_SUCCESS); function_name, utils::string::to_utf8(location), STATUS_SUCCESS);
@ -1330,9 +1257,7 @@ auto remote_server::winfsp_open(
PWSTR file_name, UINT32 create_options, UINT32 granted_access, PWSTR file_name, UINT32 create_options, UINT32 granted_access,
PVOID *file_desc, remote::file_info *file_info, PVOID *file_desc, remote::file_info *file_info,
std::string &normalized_name) -> packet::error_type { std::string &normalized_name) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto relative_path = utils::string::to_utf8(file_name); const auto relative_path = utils::string::to_utf8(file_name);
const auto file_path = construct_path(relative_path); const auto file_path = construct_path(relative_path);
@ -1349,7 +1274,12 @@ auto remote_server::winfsp_open(
auto res = open(file_path.c_str(), static_cast<int>(flags)); auto res = open(file_path.c_str(), static_cast<int>(flags));
if (res >= 0) { if (res >= 0) {
*file_desc = reinterpret_cast<PVOID>(res); *file_desc = reinterpret_cast<PVOID>(res);
set_open_info(res, open_info{0, "", nullptr, file_path}); set_open_info(res, open_info{
"",
nullptr,
{},
file_path,
});
const auto api_path = utils::path::create_api_path(relative_path); const auto api_path = utils::path::create_api_path(relative_path);
normalized_name = utils::string::replace_copy(api_path, '/', '\\'); normalized_name = utils::string::replace_copy(api_path, '/', '\\');
@ -1371,9 +1301,7 @@ auto remote_server::winfsp_overwrite(
PVOID file_desc, UINT32 attributes, BOOLEAN replace_attributes, PVOID file_desc, UINT32 attributes, BOOLEAN replace_attributes,
UINT64 /*allocation_size*/, UINT64 /*allocation_size*/,
remote::file_info *file_info) -> packet::error_type { remote::file_info *file_info) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto handle = reinterpret_cast<remote::file_handle>(file_desc); const auto handle = reinterpret_cast<remote::file_handle>(file_desc);
auto ret = static_cast<packet::error_type>( auto ret = static_cast<packet::error_type>(
@ -1403,10 +1331,9 @@ auto remote_server::winfsp_overwrite(
} }
if (set_attributes) { if (set_attributes) {
attributes &= static_cast<UINT32>( attributes &= static_cast<UINT32>(~FILE_ATTRIBUTE_NORMAL);
~(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_NORMAL));
if (attributes == 0U) { if (attributes == 0U) {
attributes = FILE_ATTRIBUTE_NORMAL; attributes = FILE_ATTRIBUTE_ARCHIVE;
} }
drive_.set_item_meta(api_path, META_ATTRIBUTES, drive_.set_item_meta(api_path, META_ATTRIBUTES,
std::to_string(attributes)); std::to_string(attributes));
@ -1429,9 +1356,7 @@ auto remote_server::winfsp_overwrite(
auto remote_server::winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, auto remote_server::winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset,
UINT32 length, PUINT32 bytes_transferred) UINT32 length, PUINT32 bytes_transferred)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
*bytes_transferred = 0; *bytes_transferred = 0;
@ -1458,9 +1383,7 @@ auto remote_server::winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset,
auto remote_server::winfsp_read_directory(PVOID file_desc, PWSTR /*pattern*/, auto remote_server::winfsp_read_directory(PVOID file_desc, PWSTR /*pattern*/,
PWSTR marker, json &item_list) PWSTR marker, json &item_list)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
item_list.clear(); item_list.clear();
@ -1496,9 +1419,7 @@ auto remote_server::winfsp_read_directory(PVOID file_desc, PWSTR /*pattern*/,
auto remote_server::winfsp_rename( auto remote_server::winfsp_rename(
PVOID /*file_desc*/, PWSTR file_name, PWSTR new_file_name, PVOID /*file_desc*/, PWSTR file_name, PWSTR new_file_name,
BOOLEAN replace_if_exists) -> packet::error_type { BOOLEAN replace_if_exists) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto relative_path = utils::string::to_utf8(file_name); const auto relative_path = utils::string::to_utf8(file_name);
const auto file_path = construct_path(relative_path); const auto file_path = construct_path(relative_path);
@ -1528,9 +1449,7 @@ auto remote_server::winfsp_set_basic_info(
PVOID file_desc, UINT32 attributes, UINT64 creation_time, PVOID file_desc, UINT32 attributes, UINT64 creation_time,
UINT64 last_access_time, UINT64 last_write_time, UINT64 change_time, UINT64 last_access_time, UINT64 last_write_time, UINT64 change_time,
remote::file_info *file_info) -> packet::error_type { remote::file_info *file_info) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto handle = reinterpret_cast<remote::file_handle>(file_desc); const auto handle = reinterpret_cast<remote::file_handle>(file_desc);
auto ret = static_cast<packet::error_type>( auto ret = static_cast<packet::error_type>(
@ -1543,15 +1462,15 @@ auto remote_server::winfsp_set_basic_info(
} else if (attributes == 0) { } else if (attributes == 0) {
attributes = utils::file::directory(file_path).exists() attributes = utils::file::directory(file_path).exists()
? FILE_ATTRIBUTE_DIRECTORY ? FILE_ATTRIBUTE_DIRECTORY
: FILE_ATTRIBUTE_NORMAL; : FILE_ATTRIBUTE_ARCHIVE;
} }
const auto api_path = construct_api_path(file_path); const auto api_path = construct_api_path(file_path);
api_meta_map meta; api_meta_map meta;
if (attributes != 0U) { if (attributes != 0U) {
if (((attributes & FILE_ATTRIBUTE_NORMAL) != 0U) && attributes &= static_cast<UINT32>(~FILE_ATTRIBUTE_NORMAL);
(attributes != FILE_ATTRIBUTE_NORMAL)) { if (attributes == 0U) {
attributes &= static_cast<UINT32>(~(FILE_ATTRIBUTE_NORMAL)); attributes |= static_cast<UINT32>(FILE_ATTRIBUTE_ARCHIVE);
} }
drive_.set_item_meta(api_path, META_ATTRIBUTES, drive_.set_item_meta(api_path, META_ATTRIBUTES,
std::to_string(attributes)); std::to_string(attributes));
@ -1596,9 +1515,7 @@ auto remote_server::winfsp_set_basic_info(
auto remote_server::winfsp_set_file_size( auto remote_server::winfsp_set_file_size(
PVOID file_desc, UINT64 new_size, BOOLEAN set_allocation_size, PVOID file_desc, UINT64 new_size, BOOLEAN set_allocation_size,
remote::file_info *file_info) -> packet::error_type { remote::file_info *file_info) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto handle = reinterpret_cast<remote::file_handle>(file_desc); const auto handle = reinterpret_cast<remote::file_handle>(file_desc);
auto ret = static_cast<packet::error_type>( auto ret = static_cast<packet::error_type>(
@ -1626,9 +1543,7 @@ auto remote_server::winfsp_set_file_size(
auto remote_server::winfsp_unmounted(const std::wstring &location) auto remote_server::winfsp_unmounted(const std::wstring &location)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
RAISE_REMOTE_FUSE_SERVER_EVENT( RAISE_REMOTE_FUSE_SERVER_EVENT(
function_name, utils::string::to_utf8(location), STATUS_SUCCESS); function_name, utils::string::to_utf8(location), STATUS_SUCCESS);
@ -1639,9 +1554,7 @@ auto remote_server::winfsp_write(
PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length, PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
BOOLEAN write_to_end, BOOLEAN constrained_io, PUINT32 bytes_transferred, BOOLEAN write_to_end, BOOLEAN constrained_io, PUINT32 bytes_transferred,
remote::file_info *file_info) -> packet::error_type { remote::file_info *file_info) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
*bytes_transferred = 0; *bytes_transferred = 0;
const auto handle = reinterpret_cast<remote::file_handle>(file_desc); const auto handle = reinterpret_cast<remote::file_handle>(file_desc);
@ -1690,9 +1603,7 @@ auto remote_server::winfsp_write(
auto remote_server::json_create_directory_snapshot( auto remote_server::json_create_directory_snapshot(
const std::string &path, json &json_data) -> packet::error_type { const std::string &path, json &json_data) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto api_path = utils::path::create_api_path(path); const auto api_path = utils::path::create_api_path(path);
const auto file_path = construct_path(api_path); const auto file_path = construct_path(api_path);
@ -1722,9 +1633,7 @@ auto remote_server::json_create_directory_snapshot(
auto remote_server::json_read_directory_snapshot( auto remote_server::json_read_directory_snapshot(
const std::string &path, const remote::file_handle &handle, const std::string &path, const remote::file_handle &handle,
std::uint32_t page, json &json_data) -> packet::error_type { std::uint32_t page, json &json_data) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
int res{-EBADF}; int res{-EBADF};
@ -1754,9 +1663,7 @@ auto remote_server::json_read_directory_snapshot(
auto remote_server::json_release_directory_snapshot( auto remote_server::json_release_directory_snapshot(
const std::string &path, const std::string &path,
const remote::file_handle &handle) -> packet::error_type { const remote::file_handle &handle) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto file_path = construct_path(path); const auto file_path = construct_path(path);
directory_cache_.remove_directory(handle); directory_cache_.remove_directory(handle);
@ -1785,7 +1692,7 @@ auto remote_server::update_to_windows_format(json &item) -> json & {
if (item["meta"][META_ATTRIBUTES].empty()) { if (item["meta"][META_ATTRIBUTES].empty()) {
item["meta"][META_ATTRIBUTES] = item["meta"][META_ATTRIBUTES] =
item["directory"].get<bool>() ? std::to_string(FILE_ATTRIBUTE_DIRECTORY) item["directory"].get<bool>() ? std::to_string(FILE_ATTRIBUTE_DIRECTORY)
: std::to_string(FILE_ATTRIBUTE_NORMAL); : std::to_string(FILE_ATTRIBUTE_ARCHIVE);
drive_.set_item_meta(api_path, META_ATTRIBUTES, drive_.set_item_meta(api_path, META_ATTRIBUTES,
item["meta"][META_ATTRIBUTES].get<std::string>()); item["meta"][META_ATTRIBUTES].get<std::string>());
} }

View File

@ -24,12 +24,13 @@
#include "events/event_system.hpp" #include "events/event_system.hpp"
#include "events/events.hpp" #include "events/events.hpp"
#include "utils/collection.hpp" #include "utils/collection.hpp"
#include "utils/config.hpp"
#include "utils/utils.hpp" #include "utils/utils.hpp"
namespace repertory { namespace repertory {
void remote_open_file_table::add_directory(const std::string &client_id, void remote_open_file_table::add_directory(const std::string &client_id,
std::uint64_t handle) { std::uint64_t handle) {
recur_mutex_lock directory_lock(directory_mutex_); recur_mutex_lock lock(file_mutex_);
auto &list = directory_lookup_[client_id]; auto &list = directory_lookup_[client_id];
if (utils::collection::excludes(list, handle)) { if (utils::collection::excludes(list, handle)) {
directory_lookup_[client_id].emplace_back(handle); directory_lookup_[client_id].emplace_back(handle);
@ -37,14 +38,32 @@ void remote_open_file_table::add_directory(const std::string &client_id,
} }
void remote_open_file_table::close_all(const std::string &client_id) { void remote_open_file_table::close_all(const std::string &client_id) {
std::vector<remote::file_handle> compat_handles; unique_recur_mutex_lock lock(file_mutex_);
unique_recur_mutex_lock compat_lock(compat_mutex_); auto compat_handles =
for (auto &&kv : compat_lookup_) { std::accumulate(compat_file_lookup_.begin(), compat_file_lookup_.end(),
if (kv.second.client_id == client_id) { std::vector<remote::file_handle>(),
compat_handles.emplace_back(kv.first); [&client_id](auto &&list, auto &&value) {
} auto &&op_info = value.second;
} if (op_info->client_id == client_id) {
compat_lock.unlock(); list.insert(list.end(), op_info->handles.begin(),
op_info->handles.end());
}
return list;
});
auto handles = std::accumulate(
file_lookup_.begin(), file_lookup_.end(), std::vector<native_handle>(),
[&client_id](auto &&list, auto &&value) {
auto &&op_info = value.second;
if (op_info->client_id == client_id) {
list.insert(list.end(), op_info->handles.begin(),
op_info->handles.end());
}
return list;
});
lock.unlock();
for (auto &&handle : compat_handles) { for (auto &&handle : compat_handles) {
#if defined(_WIN32) #if defined(_WIN32)
@ -55,32 +74,23 @@ void remote_open_file_table::close_all(const std::string &client_id) {
remove_compat_open_info(handle); remove_compat_open_info(handle);
} }
std::vector<native_handle> handles;
unique_recur_mutex_lock file_lock(file_mutex_);
for (auto &&kv : file_lookup_) {
if (kv.second.client_id == client_id) {
handles.emplace_back(kv.first);
}
}
file_lock.unlock();
for (auto &&handle : handles) { for (auto &&handle : handles) {
#if defined(_WIN32) #if defined(_WIN32)
::CloseHandle(handle); ::CloseHandle(handle);
#else #else // !defined(_WIN32)
close(handle); close(handle);
#endif #endif // defined(_WIN32)
remove_open_info(handle); remove_open_info(handle);
} }
std::vector<std::uint64_t> dirs; std::vector<std::uint64_t> dirs;
unique_recur_mutex_lock directory_lock(directory_mutex_); lock.lock();
for (auto &&kv : directory_lookup_) { for (auto &&kv : directory_lookup_) {
if (kv.first == client_id) { if (kv.first == client_id) {
dirs.insert(dirs.end(), kv.second.begin(), kv.second.end()); dirs.insert(dirs.end(), kv.second.begin(), kv.second.end());
} }
} }
directory_lock.unlock(); lock.unlock();
for (auto &&dir : dirs) { for (auto &&dir : dirs) {
remove_directory(client_id, dir); remove_directory(client_id, dir);
@ -90,123 +100,123 @@ void remote_open_file_table::close_all(const std::string &client_id) {
#if defined(_WIN32) #if defined(_WIN32)
auto remote_open_file_table::get_directory_buffer(const native_handle &handle, auto remote_open_file_table::get_directory_buffer(const native_handle &handle,
PVOID *&buffer) -> bool { PVOID *&buffer) -> bool {
recur_mutex_lock file_lock(file_mutex_); recur_mutex_lock lock(file_mutex_);
if (file_lookup_.find(handle) != file_lookup_.end()) { if (not handle_lookup_.contains(handle)) {
buffer = &file_lookup_[handle].directory_buffer; return false;
return true;
} }
return false;
buffer = &file_lookup_.at(handle_lookup_.at(handle))->directory_buffer;
return true;
} }
#endif #endif // defined(_WIN32)
auto remote_open_file_table::get_open_file_count( auto remote_open_file_table::get_open_file_count(
const std::string &file_path) const -> std::size_t { const std::string &file_path) const -> std::size_t {
unique_recur_mutex_lock file_lock(file_mutex_); recur_mutex_lock lock(file_mutex_);
const auto count = std::accumulate( return (file_lookup_.contains(file_path)
file_lookup_.cbegin(), file_lookup_.cend(), std::size_t(0U), ? file_lookup_.at(file_path)->handles.size()
[&file_path](std::size_t total, const auto &kv) -> std::size_t { : 0ULL) +
if (kv.second.path == file_path) { (compat_file_lookup_.contains(file_path)
return ++total; ? compat_file_lookup_.at(file_path)->handles.size()
} : 0ULL);
return total;
});
return std::accumulate(
compat_lookup_.cbegin(), compat_lookup_.cend(), count,
[&file_path](std::size_t total, const auto &kv) -> std::size_t {
if (kv.second.path == file_path) {
return ++total;
}
return total;
});
} }
auto remote_open_file_table::get_open_info(const native_handle &handle, auto remote_open_file_table::get_open_info(const native_handle &handle,
open_info &oi) -> bool { open_info &oi) -> bool {
recur_mutex_lock file_lock(file_mutex_); recur_mutex_lock lock(file_mutex_);
if (file_lookup_.find(handle) != file_lookup_.end()) { if (not handle_lookup_.contains(handle)) {
oi = file_lookup_[handle]; return false;
return true;
} }
return false;
oi = *file_lookup_.at(handle_lookup_.at(handle)).get();
return true;
} }
auto remote_open_file_table::get_open_file_path(const native_handle &handle) auto remote_open_file_table::get_open_file_path(const native_handle &handle)
-> std::string { -> std::string {
recur_mutex_lock file_lock(file_mutex_); recur_mutex_lock lock(file_mutex_);
if (file_lookup_.find(handle) != file_lookup_.end()) { if (not handle_lookup_.contains(handle)) {
return file_lookup_[handle].path; return "";
} }
return ""; return file_lookup_.at(handle_lookup_.at(handle))->path;
} }
auto remote_open_file_table::has_open_directory(const std::string &client_id, auto remote_open_file_table::has_open_directory(const std::string &client_id,
std::uint64_t handle) -> bool { std::uint64_t handle) -> bool {
recur_mutex_lock directory_lock(directory_mutex_); recur_mutex_lock lock(file_mutex_);
auto &list = directory_lookup_[client_id]; return (utils::collection::includes(directory_lookup_[client_id], handle));
return (utils::collection::includes(list, handle));
} }
auto remote_open_file_table::has_compat_open_info( auto remote_open_file_table::has_compat_open_info(
const remote::file_handle &handle, int error_return) -> int { const remote::file_handle &handle, int error_return) -> int {
recur_mutex_lock compat_lock(compat_mutex_); recur_mutex_lock compat_lock(file_mutex_);
const auto res = auto res = compat_handle_lookup_.contains(handle) ? 0 : -1;
((compat_lookup_.find(handle) == compat_lookup_.end()) ? -1 : 0);
if (res == -1) { if (res == -1) {
errno = error_return; errno = error_return;
} }
return res; return res;
} }
void remote_open_file_table::remove_all(const std::string &file_path) { void remote_open_file_table::remove_all(const std::string &file_path) {
unique_recur_mutex_lock file_lock(file_mutex_); unique_recur_mutex_lock lock(file_mutex_);
const auto open_list = std::accumulate( auto compat_open_list = std::accumulate(
file_lookup_.begin(), file_lookup_.end(), std::vector<native_handle>(), compat_file_lookup_.begin(), compat_file_lookup_.end(),
[&file_path](std::vector<native_handle> v,
const auto &kv) -> std::vector<native_handle> {
if (kv.second.path == file_path) {
v.emplace_back(kv.first);
}
return v;
});
const auto compat_open_list = std::accumulate(
compat_lookup_.begin(), compat_lookup_.end(),
std::vector<remote::file_handle>(), std::vector<remote::file_handle>(),
[&file_path](std::vector<remote::file_handle> v, [&file_path](auto &&list, auto &&kv) -> std::vector<remote::file_handle> {
const auto &kv) -> std::vector<remote::file_handle> { if (kv.first == file_path) {
if (kv.second.path == file_path) { auto *op_info = kv.second.get();
v.emplace_back(kv.first); list.insert(list.end(), op_info->handles.begin(),
op_info->handles.end());
} }
return v; return list;
}); });
file_lock.unlock();
for (auto &&handle : open_list) { auto open_list = std::accumulate(
remove_open_info(handle); file_lookup_.begin(), file_lookup_.end(), std::vector<native_handle>(),
} [&file_path](auto &&list, auto &&kv) -> std::vector<native_handle> {
if (kv.first == file_path) {
auto *op_info = kv.second.get();
list.insert(list.end(), op_info->handles.begin(),
op_info->handles.end());
}
return list;
});
lock.unlock();
for (auto &&handle : compat_open_list) { for (auto &&handle : compat_open_list) {
remove_compat_open_info(handle); remove_compat_open_info(handle);
} }
for (auto &&handle : open_list) {
remove_open_info(handle);
}
} }
void remote_open_file_table::remove_compat_open_info( void remote_open_file_table::remove_compat_open_info(
const remote::file_handle &handle) { const remote::file_handle &handle) {
recur_mutex_lock compat_lock(compat_mutex_); recur_mutex_lock compat_lock(file_mutex_);
if (compat_lookup_[handle].count > 0) { if (not compat_handle_lookup_.contains(handle)) {
compat_lookup_[handle].count--; return;
} }
if (not compat_lookup_[handle].count) { auto *op_info =
compat_lookup_.erase(handle); compat_file_lookup_.at(compat_handle_lookup_.at(handle)).get();
utils::collection::remove_element(op_info->handles, handle);
compat_handle_lookup_.erase(handle);
if (not op_info->handles.empty()) {
return;
} }
auto path = op_info->path;
compat_file_lookup_.erase(path);
} }
auto remote_open_file_table::remove_directory(const std::string &client_id, auto remote_open_file_table::remove_directory(const std::string &client_id,
std::uint64_t handle) -> bool { std::uint64_t handle) -> bool {
recur_mutex_lock directory_lock(directory_mutex_); recur_mutex_lock lock(file_mutex_);
auto &list = directory_lookup_[client_id]; auto &list = directory_lookup_[client_id];
if (utils::collection::includes(list, handle)) { if (utils::collection::includes(list, handle)) {
utils::collection::remove_element(list, handle); utils::collection::remove_element(list, handle);
@ -220,48 +230,93 @@ auto remote_open_file_table::remove_directory(const std::string &client_id,
} }
void remote_open_file_table::remove_open_info(const native_handle &handle) { void remote_open_file_table::remove_open_info(const native_handle &handle) {
recur_mutex_lock file_lock(file_mutex_); recur_mutex_lock lock(file_mutex_);
if (file_lookup_[handle].count > 0) { if (not handle_lookup_.contains(handle)) {
file_lookup_[handle].count--; return;
} }
if (not file_lookup_[handle].count) {
auto *op_info = file_lookup_.at(handle_lookup_.at(handle)).get();
utils::collection::remove_element(op_info->handles, handle);
handle_lookup_.erase(handle);
if (not op_info->handles.empty()) {
return;
}
#if defined(_WIN32) #if defined(_WIN32)
if (file_lookup_[handle].directory_buffer) { if (op_info->directory_buffer) {
FspFileSystemDeleteDirectoryBuffer( FspFileSystemDeleteDirectoryBuffer(&op_info->directory_buffer);
&file_lookup_[handle].directory_buffer); }
}
#endif #endif
file_lookup_.erase(handle);
auto path = op_info->path;
file_lookup_.erase(path);
}
void remote_open_file_table::remove_and_close_all(const native_handle &handle) {
unique_recur_mutex_lock lock(file_mutex_);
if (not handle_lookup_.contains(handle)) {
return;
}
auto op_info = *file_lookup_.at(handle_lookup_.at(handle));
lock.unlock();
for (auto &&open_handle : op_info.handles) {
#if defined(_WIN32)
::CloseHandle(open_handle);
#else // !defined(_WIN32)
close(open_handle);
#endif // defined(_WIN32)
remove_open_info(open_handle);
} }
} }
void remote_open_file_table::set_compat_client_id( void remote_open_file_table::set_compat_client_id(
const remote::file_handle &handle, const std::string &client_id) { const remote::file_handle &handle, const std::string &client_id) {
recur_mutex_lock compat_lock(compat_mutex_); recur_mutex_lock compat_lock(file_mutex_);
compat_lookup_[handle].client_id = client_id; compat_file_lookup_.at(compat_handle_lookup_.at(handle))->client_id =
client_id;
} }
void remote_open_file_table::set_client_id(const native_handle &handle, void remote_open_file_table::set_client_id(const native_handle &handle,
const std::string &client_id) { const std::string &client_id) {
recur_mutex_lock file_lock(file_mutex_); recur_mutex_lock lock(file_mutex_);
file_lookup_[handle].client_id = client_id; file_lookup_.at(handle_lookup_.at(handle))->client_id = client_id;
} }
void remote_open_file_table::set_compat_open_info( void remote_open_file_table::set_compat_open_info(
const remote::file_handle &handle, const std::string &file_path) { const remote::file_handle &handle, const std::string &file_path) {
recur_mutex_lock compat_lock(compat_mutex_); recur_mutex_lock compat_lock(file_mutex_);
if (compat_lookup_.find(handle) == compat_lookup_.end()) { if (compat_handle_lookup_.contains(handle)) {
compat_lookup_[handle] = {0, "", file_path}; return;
} }
compat_lookup_[handle].count++;
if (not compat_file_lookup_.contains(file_path)) {
compat_file_lookup_[file_path] =
std::make_unique<compat_open_info>(compat_open_info{
"",
{},
file_path,
});
}
compat_handle_lookup_[handle] = file_path;
compat_file_lookup_.at(file_path)->handles.emplace_back(handle);
} }
void remote_open_file_table::set_open_info(const native_handle &handle, void remote_open_file_table::set_open_info(const native_handle &handle,
open_info oi) { open_info op_info) {
recur_mutex_lock file_lock(file_mutex_); recur_mutex_lock lock(file_mutex_);
if (file_lookup_.find(handle) == file_lookup_.end()) { if (handle_lookup_.contains(handle)) {
file_lookup_[handle] = std::move(oi); return;
} }
file_lookup_[handle].count++;
if (not file_lookup_.contains(op_info.path)) {
file_lookup_[op_info.path] = std::make_unique<open_info>(op_info);
}
handle_lookup_[handle] = op_info.path;
file_lookup_.at(op_info.path)->handles.emplace_back(handle);
} }
} // namespace repertory } // namespace repertory

View File

@ -47,18 +47,11 @@ E_SIMPLE3(remote_winfsp_client_event, debug, true,
// clang-format on // clang-format on
remote_client::remote_client(const app_config &config) remote_client::remote_client(const app_config &config)
: config_(config), : config_(config), packet_client_(config.get_remote_config()) {}
packet_client_(
config.get_remote_host_name_or_ip(),
config.get_remote_max_connections(), config.get_remote_port(),
config.get_remote_receive_timeout_secs(),
config.get_remote_send_timeout_secs(), config.get_remote_token()) {}
auto remote_client::winfsp_can_delete(PVOID file_desc, auto remote_client::winfsp_can_delete(PVOID file_desc, PWSTR file_name)
PWSTR file_name) -> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(file_desc); request.encode(file_desc);
@ -75,11 +68,10 @@ auto remote_client::winfsp_can_delete(PVOID file_desc,
return ret; return ret;
} }
auto remote_client::json_create_directory_snapshot( auto remote_client::json_create_directory_snapshot(const std::string &path,
const std::string &path, json &json_data) -> packet::error_type { json &json_data)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -100,9 +92,7 @@ auto remote_client::json_create_directory_snapshot(
auto remote_client::json_read_directory_snapshot( auto remote_client::json_read_directory_snapshot(
const std::string &path, const remote::file_handle &handle, const std::string &path, const remote::file_handle &handle,
std::uint32_t page, json &json_data) -> packet::error_type { std::uint32_t page, json &json_data) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -123,11 +113,9 @@ auto remote_client::json_read_directory_snapshot(
} }
auto remote_client::json_release_directory_snapshot( auto remote_client::json_release_directory_snapshot(
const std::string &path, const std::string &path, const remote::file_handle &handle)
const remote::file_handle &handle) -> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(path); request.encode(path);
@ -143,11 +131,9 @@ auto remote_client::json_release_directory_snapshot(
} }
auto remote_client::winfsp_cleanup(PVOID file_desc, PWSTR file_name, auto remote_client::winfsp_cleanup(PVOID file_desc, PWSTR file_name,
UINT32 flags, UINT32 flags, BOOLEAN &was_deleted)
BOOLEAN &was_closed) -> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
auto handle{ auto handle{
to_handle(file_desc), to_handle(file_desc),
@ -157,7 +143,7 @@ auto remote_client::winfsp_cleanup(PVOID file_desc, PWSTR file_name,
get_open_file_path(handle), get_open_file_path(handle),
}; };
was_closed = 0; was_deleted = 0U;
packet request; packet request;
request.encode(file_desc); request.encode(file_desc);
@ -169,18 +155,18 @@ auto remote_client::winfsp_cleanup(PVOID file_desc, PWSTR file_name,
auto ret{ auto ret{
packet_client_.send(function_name, request, response, service_flags), packet_client_.send(function_name, request, response, service_flags),
}; };
DECODE_OR_IGNORE(&response, was_closed);
if (was_closed != 0U) { DECODE_OR_IGNORE(&response, was_deleted);
if (was_deleted != 0U) {
remove_all(file_path); remove_all(file_path);
} }
RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, file_path, ret); RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, file_path, ret);
return ret; return ret;
} }
auto remote_client::winfsp_close(PVOID file_desc) -> packet::error_type { auto remote_client::winfsp_close(PVOID file_desc) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
auto handle{ auto handle{
to_handle(file_desc), to_handle(file_desc),
@ -211,11 +197,9 @@ auto remote_client::winfsp_create(PWSTR file_name, UINT32 create_options,
UINT32 granted_access, UINT32 attributes, UINT32 granted_access, UINT32 attributes,
UINT64 allocation_size, PVOID *file_desc, UINT64 allocation_size, PVOID *file_desc,
remote::file_info *file_info, remote::file_info *file_info,
std::string &normalized_name, std::string &normalized_name, BOOLEAN &exists)
BOOLEAN &exists) -> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(file_name); request.encode(file_name);
@ -235,11 +219,16 @@ auto remote_client::winfsp_create(PWSTR file_name, UINT32 create_options,
DECODE_OR_IGNORE(&response, *file_info); DECODE_OR_IGNORE(&response, *file_info);
DECODE_OR_IGNORE(&response, normalized_name); DECODE_OR_IGNORE(&response, normalized_name);
DECODE_OR_IGNORE(&response, exists); DECODE_OR_IGNORE(&response, exists);
if (ret == STATUS_SUCCESS) { if (ret == STATUS_SUCCESS) {
*file_desc = reinterpret_cast<PVOID>(handle); *file_desc = reinterpret_cast<PVOID>(handle);
set_open_info( set_open_info(to_handle(*file_desc),
to_handle(*file_desc), open_info{
open_info{0, "", nullptr, utils::string::to_utf8(file_name)}); "",
nullptr,
{},
utils::string::to_utf8(file_name),
});
#if defined(_WIN32) #if defined(_WIN32)
if (exists) { if (exists) {
::SetLastError(ERROR_ALREADY_EXISTS); ::SetLastError(ERROR_ALREADY_EXISTS);
@ -255,9 +244,7 @@ auto remote_client::winfsp_create(PWSTR file_name, UINT32 create_options,
auto remote_client::winfsp_flush(PVOID file_desc, remote::file_info *file_info) auto remote_client::winfsp_flush(PVOID file_desc, remote::file_info *file_info)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(file_desc); request.encode(file_desc);
@ -285,11 +272,10 @@ auto remote_client::winfsp_get_dir_buffer([[maybe_unused]] PVOID file_desc,
return static_cast<packet::error_type>(STATUS_INVALID_HANDLE); return static_cast<packet::error_type>(STATUS_INVALID_HANDLE);
} }
auto remote_client::winfsp_get_file_info( auto remote_client::winfsp_get_file_info(PVOID file_desc,
PVOID file_desc, remote::file_info *file_info) -> packet::error_type { remote::file_info *file_info)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
packet request; packet request;
request.encode(file_desc); request.encode(file_desc);
@ -306,12 +292,12 @@ auto remote_client::winfsp_get_file_info(
return ret; return ret;
} }
auto remote_client::winfsp_get_security_by_name( auto remote_client::winfsp_get_security_by_name(PWSTR file_name,
PWSTR file_name, PUINT32 attributes, std::uint64_t *descriptor_size, PUINT32 attributes,
std::wstring &string_descriptor) -> packet::error_type { std::uint64_t *descriptor_size,
static constexpr const std::string_view function_name{ std::wstring &string_descriptor)
static_cast<const char *>(__FUNCTION__), -> packet::error_type {
}; REPERTORY_USES_FUNCTION_NAME();
packet request; packet request;
request.encode(file_name); request.encode(file_name);
@ -340,12 +326,11 @@ auto remote_client::winfsp_get_security_by_name(
return ret; return ret;
} }
auto remote_client::winfsp_get_volume_info( auto remote_client::winfsp_get_volume_info(UINT64 &total_size,
UINT64 &total_size, UINT64 &free_size, UINT64 &free_size,
std::string &volume_label) -> packet::error_type { std::string &volume_label)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
packet request; packet request;
packet response; packet response;
@ -362,9 +347,7 @@ auto remote_client::winfsp_get_volume_info(
auto remote_client::winfsp_mounted(const std::wstring &location) auto remote_client::winfsp_mounted(const std::wstring &location)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(std::string{project_get_version()}); request.encode(std::string{project_get_version()});
@ -384,13 +367,12 @@ auto remote_client::winfsp_mounted(const std::wstring &location)
return ret; return ret;
} }
auto remote_client::winfsp_open( auto remote_client::winfsp_open(PWSTR file_name, UINT32 create_options,
PWSTR file_name, UINT32 create_options, UINT32 granted_access, UINT32 granted_access, PVOID *file_desc,
PVOID *file_desc, remote::file_info *file_info, remote::file_info *file_info,
std::string &normalized_name) -> packet::error_type { std::string &normalized_name)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
packet request; packet request;
request.encode(file_name); request.encode(file_name);
@ -410,9 +392,13 @@ auto remote_client::winfsp_open(
if (ret == STATUS_SUCCESS) { if (ret == STATUS_SUCCESS) {
*file_desc = reinterpret_cast<PVOID>(handle); *file_desc = reinterpret_cast<PVOID>(handle);
set_open_info( set_open_info(to_handle(*file_desc),
to_handle(*file_desc), open_info{
open_info{0, "", nullptr, utils::string::to_utf8(file_name)}); "",
nullptr,
{},
utils::string::to_utf8(file_name),
});
} }
} }
@ -421,13 +407,12 @@ auto remote_client::winfsp_open(
return ret; return ret;
} }
auto remote_client::winfsp_overwrite( auto remote_client::winfsp_overwrite(PVOID file_desc, UINT32 attributes,
PVOID file_desc, UINT32 attributes, BOOLEAN replace_attributes, BOOLEAN replace_attributes,
UINT64 allocation_size, UINT64 allocation_size,
remote::file_info *file_info) -> packet::error_type { remote::file_info *file_info)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
packet request; packet request;
request.encode(file_desc); request.encode(file_desc);
@ -450,9 +435,7 @@ auto remote_client::winfsp_overwrite(
auto remote_client::winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, auto remote_client::winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset,
UINT32 length, PUINT32 bytes_transferred) UINT32 length, PUINT32 bytes_transferred)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(file_desc); request.encode(file_desc);
@ -469,7 +452,7 @@ auto remote_client::winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset,
ret = response.decode(buffer, *bytes_transferred); ret = response.decode(buffer, *bytes_transferred);
#if defined(_WIN32) #if defined(_WIN32)
if ((ret == STATUS_SUCCESS) && if ((ret == STATUS_SUCCESS) &&
(not *bytes_transferred || (*bytes_transferred != length))) { (not*bytes_transferred || (*bytes_transferred != length))) {
::SetLastError(ERROR_HANDLE_EOF); ::SetLastError(ERROR_HANDLE_EOF);
} }
#endif #endif
@ -486,9 +469,7 @@ auto remote_client::winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset,
auto remote_client::winfsp_read_directory(PVOID file_desc, PWSTR pattern, auto remote_client::winfsp_read_directory(PVOID file_desc, PWSTR pattern,
PWSTR marker, json &item_list) PWSTR marker, json &item_list)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(file_desc); request.encode(file_desc);
@ -509,12 +490,11 @@ auto remote_client::winfsp_read_directory(PVOID file_desc, PWSTR pattern,
return ret; return ret;
} }
auto remote_client::winfsp_rename( auto remote_client::winfsp_rename(PVOID file_desc, PWSTR file_name,
PVOID file_desc, PWSTR file_name, PWSTR new_file_name, PWSTR new_file_name,
BOOLEAN replace_if_exists) -> packet::error_type { BOOLEAN replace_if_exists)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
packet request; packet request;
request.encode(file_desc); request.encode(file_desc);
@ -539,9 +519,7 @@ auto remote_client::winfsp_set_basic_info(
PVOID file_desc, UINT32 attributes, UINT64 creation_time, PVOID file_desc, UINT32 attributes, UINT64 creation_time,
UINT64 last_access_time, UINT64 last_write_time, UINT64 change_time, UINT64 last_access_time, UINT64 last_write_time, UINT64 change_time,
remote::file_info *file_info) -> packet::error_type { remote::file_info *file_info) -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
packet request; packet request;
request.encode(file_desc); request.encode(file_desc);
@ -563,12 +541,11 @@ auto remote_client::winfsp_set_basic_info(
return ret; return ret;
} }
auto remote_client::winfsp_set_file_size( auto remote_client::winfsp_set_file_size(PVOID file_desc, UINT64 new_size,
PVOID file_desc, UINT64 new_size, BOOLEAN set_allocation_size, BOOLEAN set_allocation_size,
remote::file_info *file_info) -> packet::error_type { remote::file_info *file_info)
static constexpr const std::string_view function_name{ -> packet::error_type {
static_cast<const char *>(__FUNCTION__), REPERTORY_USES_FUNCTION_NAME();
};
packet request; packet request;
request.encode(file_desc); request.encode(file_desc);
@ -589,9 +566,7 @@ auto remote_client::winfsp_set_file_size(
auto remote_client::winfsp_unmounted(const std::wstring &location) auto remote_client::winfsp_unmounted(const std::wstring &location)
-> packet::error_type { -> packet::error_type {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
auto mount_location{ auto mount_location{
utils::string::to_utf8(location), utils::string::to_utf8(location),
@ -610,13 +585,13 @@ auto remote_client::winfsp_unmounted(const std::wstring &location)
return ret; return ret;
} }
auto remote_client::winfsp_write( auto remote_client::winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset,
PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length, UINT32 length, BOOLEAN write_to_end,
BOOLEAN write_to_end, BOOLEAN constrained_io, PUINT32 bytes_transferred, BOOLEAN constrained_io,
remote::file_info *file_info) -> packet::error_type { PUINT32 bytes_transferred,
static constexpr const std::string_view function_name{ remote::file_info *file_info)
static_cast<const char *>(__FUNCTION__), -> packet::error_type {
}; REPERTORY_USES_FUNCTION_NAME();
packet request; packet request;
request.encode(file_desc); request.encode(file_desc);

View File

@ -41,22 +41,19 @@ namespace repertory::remote_winfsp {
remote_winfsp_drive::winfsp_service::winfsp_service( remote_winfsp_drive::winfsp_service::winfsp_service(
lock_data &lock, remote_winfsp_drive &drive, lock_data &lock, remote_winfsp_drive &drive,
std::vector<std::string> drive_args, app_config &config) std::vector<std::string> drive_args, app_config &config)
: Service(&(L"RepertoryRemote_" + : Service(std::wstring{REPERTORY_W}.data()),
utils::string::from_utf8(lock.get_unique_id()))[0U]),
config_(config), config_(config),
lock_(lock),
drive_(drive), drive_(drive),
drive_args_(std::move(drive_args)), drive_args_(std::move(drive_args)),
host_(drive) {} host_(drive),
lock_(lock) {}
auto remote_winfsp_drive::winfsp_service::OnStart(ULONG, PWSTR *) -> NTSTATUS { auto remote_winfsp_drive::winfsp_service::OnStart(ULONG, PWSTR *) -> NTSTATUS {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
const auto mount_location = utils::string::to_lower(utils::path::absolute( auto mount_location = utils::string::to_lower(utils::path::absolute(
(drive_args_.size() > 1U) ? drive_args_.at(1U) : "")); (drive_args_.size() > 1U) ? drive_args_.at(1U) : ""));
const auto drive_letter = auto drive_letter =
((mount_location.size() == 2U) || ((mount_location.size() == 2U) ||
((mount_location.size() == 3U) && (mount_location.at(2U) == '\\'))) && ((mount_location.size() == 3U) && (mount_location.at(2U) == '\\'))) &&
(mount_location.at(1U) == ':'); (mount_location.at(1U) == ':');
@ -88,9 +85,7 @@ auto remote_winfsp_drive::winfsp_service::OnStart(ULONG, PWSTR *) -> NTSTATUS {
} }
auto remote_winfsp_drive::winfsp_service::OnStop() -> NTSTATUS { auto remote_winfsp_drive::winfsp_service::OnStop() -> NTSTATUS {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
host_.Unmount(); host_.Unmount();
if (not lock_.set_mount_state(false, "", -1)) { if (not lock_.set_mount_state(false, "", -1)) {
@ -119,8 +114,8 @@ auto remote_winfsp_drive::CanDelete(PVOID /*file_node*/, PVOID file_desc,
VOID remote_winfsp_drive::Cleanup(PVOID /*file_node*/, PVOID file_desc, VOID remote_winfsp_drive::Cleanup(PVOID /*file_node*/, PVOID file_desc,
PWSTR file_name, ULONG flags) { PWSTR file_name, ULONG flags) {
BOOLEAN was_closed{}; BOOLEAN was_deleted{};
remote_instance_->winfsp_cleanup(file_desc, file_name, flags, was_closed); remote_instance_->winfsp_cleanup(file_desc, file_name, flags, was_deleted);
} }
VOID remote_winfsp_drive::Close(PVOID /*file_node*/, PVOID file_desc) { VOID remote_winfsp_drive::Close(PVOID /*file_node*/, PVOID file_desc) {
@ -131,8 +126,8 @@ auto remote_winfsp_drive::Create(PWSTR file_name, UINT32 create_options,
UINT32 granted_access, UINT32 attributes, UINT32 granted_access, UINT32 attributes,
PSECURITY_DESCRIPTOR /*descriptor*/, PSECURITY_DESCRIPTOR /*descriptor*/,
UINT64 allocation_size, PVOID * /*file_node*/, UINT64 allocation_size, PVOID * /*file_node*/,
PVOID *file_desc, PVOID *file_desc, OpenFileInfo *ofi)
OpenFileInfo *ofi) -> NTSTATUS { -> NTSTATUS {
remote::file_info fi{}; remote::file_info fi{};
std::string normalized_name; std::string normalized_name;
BOOLEAN exists = 0; BOOLEAN exists = 0;
@ -141,7 +136,7 @@ auto remote_winfsp_drive::Create(PWSTR file_name, UINT32 create_options,
file_desc, &fi, normalized_name, exists); file_desc, &fi, normalized_name, exists);
if (ret == STATUS_SUCCESS) { if (ret == STATUS_SUCCESS) {
set_file_info(ofi->FileInfo, fi); set_file_info(ofi->FileInfo, fi);
const auto file_path = utils::string::from_utf8(normalized_name); auto file_path = utils::string::from_utf8(normalized_name);
wcsncpy(ofi->NormalizedName, file_path.data(), wcslen(file_path.c_str())); wcsncpy(ofi->NormalizedName, file_path.data(), wcslen(file_path.c_str()));
ofi->NormalizedNameSize = ofi->NormalizedNameSize =
static_cast<UINT16>(wcslen(file_path.c_str()) * sizeof(WCHAR)); static_cast<UINT16>(wcslen(file_path.c_str()) * sizeof(WCHAR));
@ -166,9 +161,10 @@ auto remote_winfsp_drive::GetFileInfo(PVOID /*file_node*/, PVOID file_desc,
return ret; return ret;
} }
auto remote_winfsp_drive::GetSecurityByName( auto remote_winfsp_drive::GetSecurityByName(PWSTR file_name, PUINT32 attributes,
PWSTR file_name, PUINT32 attributes, PSECURITY_DESCRIPTOR descriptor, PSECURITY_DESCRIPTOR descriptor,
SIZE_T *descriptor_size) -> NTSTATUS { SIZE_T *descriptor_size)
-> NTSTATUS {
std::wstring string_descriptor; std::wstring string_descriptor;
std::uint64_t sds = (descriptor_size == nullptr) ? 0 : *descriptor_size; std::uint64_t sds = (descriptor_size == nullptr) ? 0 : *descriptor_size;
auto ret = remote_instance_->winfsp_get_security_by_name( auto ret = remote_instance_->winfsp_get_security_by_name(
@ -199,8 +195,7 @@ auto remote_winfsp_drive::GetVolumeInfo(VolumeInfo *volume_info) -> NTSTATUS {
auto ret = remote_instance_->winfsp_get_volume_info( auto ret = remote_instance_->winfsp_get_volume_info(
volume_info->TotalSize, volume_info->FreeSize, volume_label); volume_info->TotalSize, volume_info->FreeSize, volume_label);
if (ret == STATUS_SUCCESS) { if (ret == STATUS_SUCCESS) {
const auto byte_size = auto byte_size = static_cast<UINT16>(volume_label.size() * sizeof(WCHAR));
static_cast<UINT16>(volume_label.size() * sizeof(WCHAR));
wcscpy_s(&volume_info->VolumeLabel[0U], 32, wcscpy_s(&volume_info->VolumeLabel[0U], 32,
utils::string::from_utf8(volume_label).c_str()); utils::string::from_utf8(volume_label).c_str());
volume_info->VolumeLabelLength = volume_info->VolumeLabelLength =
@ -216,20 +211,21 @@ auto remote_winfsp_drive::Init(PVOID host) -> NTSTATUS {
&(L"\\repertory\\" + &(L"\\repertory\\" +
std::wstring(file_system_host->FileSystemName()).substr(0U, 1U))[0U]); std::wstring(file_system_host->FileSystemName()).substr(0U, 1U))[0U]);
} }
file_system_host->SetFileSystemName(std::wstring{REPERTORY_W}.data());
file_system_host->SetCasePreservedNames(TRUE);
file_system_host->SetCaseSensitiveSearch(TRUE);
file_system_host->SetFileInfoTimeout(1000);
file_system_host->SetFlushAndPurgeOnCleanup(TRUE); file_system_host->SetFlushAndPurgeOnCleanup(TRUE);
file_system_host->SetMaxComponentLength(255U);
file_system_host->SetNamedStreams(FALSE);
file_system_host->SetPassQueryDirectoryPattern(FALSE);
file_system_host->SetPersistentAcls(FALSE);
file_system_host->SetPostCleanupWhenModifiedOnly(TRUE);
file_system_host->SetReparsePoints(FALSE); file_system_host->SetReparsePoints(FALSE);
file_system_host->SetReparsePointsAccessCheck(FALSE); file_system_host->SetReparsePointsAccessCheck(FALSE);
file_system_host->SetSectorSize(WINFSP_ALLOCATION_UNIT); file_system_host->SetSectorSize(WINFSP_ALLOCATION_UNIT);
file_system_host->SetSectorsPerAllocationUnit(1); file_system_host->SetSectorsPerAllocationUnit(1);
file_system_host->SetFileInfoTimeout(1000);
file_system_host->SetCaseSensitiveSearch(FALSE);
file_system_host->SetCasePreservedNames(TRUE);
file_system_host->SetNamedStreams(FALSE);
file_system_host->SetUnicodeOnDisk(TRUE); file_system_host->SetUnicodeOnDisk(TRUE);
file_system_host->SetPersistentAcls(FALSE);
file_system_host->SetPostCleanupWhenModifiedOnly(TRUE);
file_system_host->SetPassQueryDirectoryPattern(FALSE);
file_system_host->SetVolumeCreationTime(utils::time::get_time_now()); file_system_host->SetVolumeCreationTime(utils::time::get_time_now());
file_system_host->SetVolumeSerialNumber(0); file_system_host->SetVolumeSerialNumber(0);
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -239,10 +235,10 @@ auto remote_winfsp_drive::mount(const std::vector<std::string> &drive_args)
-> int { -> 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 (const auto &arg : drive_args) { for (auto &&arg : drive_args) {
if (arg == "-f") { if (arg == "-f") {
if (not force_no_console) { if (not force_no_console) {
enable_console = true; enable_console = true;
@ -266,9 +262,7 @@ auto remote_winfsp_drive::mount(const std::vector<std::string> &drive_args)
} }
auto remote_winfsp_drive::Mounted(PVOID host) -> NTSTATUS { auto remote_winfsp_drive::Mounted(PVOID host) -> NTSTATUS {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
auto *file_system_host = reinterpret_cast<FileSystemHost *>(host); auto *file_system_host = reinterpret_cast<FileSystemHost *>(host);
remote_instance_ = factory_(); remote_instance_ = factory_();
@ -285,8 +279,8 @@ auto remote_winfsp_drive::Mounted(PVOID host) -> NTSTATUS {
auto remote_winfsp_drive::Open(PWSTR file_name, UINT32 create_options, auto remote_winfsp_drive::Open(PWSTR file_name, UINT32 create_options,
UINT32 granted_access, PVOID * /*file_node*/, UINT32 granted_access, PVOID * /*file_node*/,
PVOID *file_desc, PVOID *file_desc, OpenFileInfo *ofi)
OpenFileInfo *ofi) -> NTSTATUS { -> NTSTATUS {
remote::file_info fi{}; remote::file_info fi{};
std::string normalize_name; std::string normalize_name;
auto ret = auto ret =
@ -294,7 +288,7 @@ auto remote_winfsp_drive::Open(PWSTR file_name, UINT32 create_options,
file_desc, &fi, normalize_name); file_desc, &fi, normalize_name);
if (ret == STATUS_SUCCESS) { if (ret == STATUS_SUCCESS) {
set_file_info(ofi->FileInfo, fi); set_file_info(ofi->FileInfo, fi);
const auto file_path = utils::string::from_utf8(normalize_name); auto file_path = utils::string::from_utf8(normalize_name);
wcsncpy(ofi->NormalizedName, file_path.data(), wcslen(file_path.c_str())); wcsncpy(ofi->NormalizedName, file_path.data(), wcslen(file_path.c_str()));
ofi->NormalizedNameSize = ofi->NormalizedNameSize =
static_cast<UINT16>(wcslen(file_path.c_str()) * sizeof(WCHAR)); static_cast<UINT16>(wcslen(file_path.c_str()) * sizeof(WCHAR));
@ -306,29 +300,29 @@ auto remote_winfsp_drive::Open(PWSTR file_name, UINT32 create_options,
auto remote_winfsp_drive::Overwrite(PVOID /*file_node*/, PVOID file_desc, auto remote_winfsp_drive::Overwrite(PVOID /*file_node*/, PVOID file_desc,
UINT32 attributes, UINT32 attributes,
BOOLEAN replace_attributes, BOOLEAN replace_attributes,
UINT64 allocation_size, UINT64 allocation_size, FileInfo *file_info)
FileInfo *file_info) -> NTSTATUS { -> NTSTATUS {
remote::file_info fi{}; remote::file_info info{};
auto ret = remote_instance_->winfsp_overwrite( auto ret = remote_instance_->winfsp_overwrite(
file_desc, attributes, replace_attributes, allocation_size, &fi); file_desc, attributes, replace_attributes, allocation_size, &info);
set_file_info(*file_info, fi); set_file_info(*file_info, info);
return ret; return ret;
} }
void remote_winfsp_drive::populate_file_info(const json &item, void remote_winfsp_drive::populate_file_info(const json &item,
FSP_FSCTL_FILE_INFO &file_info) { FSP_FSCTL_FILE_INFO &file_info) {
const auto di = directory_item::from_json(item); auto dir_item = item.get<directory_item>();
file_info.FileSize = di.directory ? 0 : di.size; file_info.FileSize = dir_item.directory ? 0 : dir_item.size;
file_info.AllocationSize = file_info.AllocationSize =
utils::divide_with_ceiling(file_info.FileSize, WINFSP_ALLOCATION_UNIT) * utils::divide_with_ceiling(file_info.FileSize, WINFSP_ALLOCATION_UNIT) *
WINFSP_ALLOCATION_UNIT; WINFSP_ALLOCATION_UNIT;
file_info.ChangeTime = utils::get_changed_time_from_meta(di.meta); file_info.ChangeTime = utils::get_changed_time_from_meta(dir_item.meta);
file_info.CreationTime = utils::get_creation_time_from_meta(di.meta); file_info.CreationTime = utils::get_creation_time_from_meta(dir_item.meta);
file_info.FileAttributes = utils::get_attributes_from_meta(di.meta); file_info.FileAttributes = utils::get_attributes_from_meta(dir_item.meta);
file_info.HardLinks = 0; file_info.HardLinks = 0;
file_info.IndexNumber = 0; file_info.IndexNumber = 0;
file_info.LastAccessTime = utils::get_accessed_time_from_meta(di.meta); file_info.LastAccessTime = utils::get_accessed_time_from_meta(dir_item.meta);
file_info.LastWriteTime = utils::get_written_time_from_meta(di.meta); file_info.LastWriteTime = utils::get_written_time_from_meta(dir_item.meta);
file_info.ReparseTag = 0; file_info.ReparseTag = 0;
file_info.EaSize = 0; file_info.EaSize = 0;
} }
@ -358,15 +352,15 @@ auto remote_winfsp_drive::ReadDirectory(PVOID /*file_node*/, PVOID file_desc,
directory_buffer, static_cast<BOOLEAN>(nullptr == marker), directory_buffer, static_cast<BOOLEAN>(nullptr == marker),
&ret)) { &ret)) {
auto item_found = false; auto item_found = false;
for (const auto &item : item_list) { for (auto &&item : item_list) {
const auto item_path = item["path"].get<std::string>(); auto item_path = item["path"].get<std::string>();
const auto display_name = utils::string::from_utf8( auto display_name = utils::string::from_utf8(
utils::path::strip_to_file_name(item_path)); utils::path::strip_to_file_name(item_path));
if (not marker || (marker && item_found)) { if (not marker || (marker && item_found)) {
// if (not utils::path::is_ads_file_path(item_path)) { // if (not utils::path::is_ads_file_path(item_path)) {
union { union {
UINT8 B[FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) + UINT8 B[FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) +
((MAX_PATH + 1) * sizeof(WCHAR))]; ((repertory::max_path_length + 1U) * sizeof(WCHAR))];
FSP_FSCTL_DIR_INFO D; FSP_FSCTL_DIR_INFO D;
} directory_info_buffer; } directory_info_buffer;
@ -374,7 +368,8 @@ auto remote_winfsp_drive::ReadDirectory(PVOID /*file_node*/, PVOID file_desc,
::ZeroMemory(directory_info, sizeof(*directory_info)); ::ZeroMemory(directory_info, sizeof(*directory_info));
directory_info->Size = static_cast<UINT16>( directory_info->Size = static_cast<UINT16>(
FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) + FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) +
(std::min(static_cast<size_t>(MAX_PATH), display_name.size()) * (std::min(static_cast<size_t>(repertory::max_path_length),
display_name.size()) *
sizeof(WCHAR))); sizeof(WCHAR)));
if (not item["meta"].empty() || if (not item["meta"].empty() ||
@ -382,8 +377,8 @@ auto remote_winfsp_drive::ReadDirectory(PVOID /*file_node*/, PVOID file_desc,
populate_file_info(item, directory_info->FileInfo); populate_file_info(item, directory_info->FileInfo);
} }
if (ret == STATUS_SUCCESS) { if (ret == STATUS_SUCCESS) {
::wcscpy_s(&directory_info->FileNameBuf[0], MAX_PATH, ::wcscpy_s(&directory_info->FileNameBuf[0],
&display_name[0]); repertory::max_path_length, &display_name[0]);
FspFileSystemFillDirectoryBuffer(directory_buffer, directory_info, FspFileSystemFillDirectoryBuffer(directory_buffer, directory_info,
&ret); &ret);
@ -423,8 +418,8 @@ auto remote_winfsp_drive::SetBasicInfo(PVOID /*file_node*/, PVOID file_desc,
UINT32 attributes, UINT64 creation_time, UINT32 attributes, UINT64 creation_time,
UINT64 last_access_time, UINT64 last_access_time,
UINT64 last_write_time, UINT64 last_write_time,
UINT64 change_time, UINT64 change_time, FileInfo *file_info)
FileInfo *file_info) -> NTSTATUS { -> NTSTATUS {
remote::file_info fi{}; remote::file_info fi{};
auto ret = remote_instance_->winfsp_set_basic_info( auto ret = remote_instance_->winfsp_set_basic_info(
file_desc, attributes, creation_time, last_access_time, last_write_time, file_desc, attributes, creation_time, last_access_time, last_write_time,
@ -460,9 +455,7 @@ auto remote_winfsp_drive::SetFileSize(PVOID /*file_node*/, PVOID file_desc,
} }
VOID remote_winfsp_drive::Unmounted(PVOID host) { VOID remote_winfsp_drive::Unmounted(PVOID host) {
static constexpr const std::string_view function_name{ REPERTORY_USES_FUNCTION_NAME();
static_cast<const char *>(__FUNCTION__),
};
server_->stop(); server_->stop();
server_.reset(); server_.reset();
@ -478,8 +471,8 @@ VOID remote_winfsp_drive::Unmounted(PVOID host) {
auto remote_winfsp_drive::Write(PVOID /*file_node*/, PVOID file_desc, auto remote_winfsp_drive::Write(PVOID /*file_node*/, PVOID file_desc,
PVOID buffer, UINT64 offset, ULONG length, PVOID buffer, UINT64 offset, ULONG length,
BOOLEAN write_to_end, BOOLEAN constrained_io, BOOLEAN write_to_end, BOOLEAN constrained_io,
PULONG bytes_transferred, PULONG bytes_transferred, FileInfo *file_info)
FileInfo *file_info) -> NTSTATUS { -> NTSTATUS {
remote::file_info fi{}; remote::file_info fi{};
auto ret = remote_instance_->winfsp_write( auto ret = remote_instance_->winfsp_write(
file_desc, buffer, offset, length, write_to_end, constrained_io, file_desc, buffer, offset, length, write_to_end, constrained_io,

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,8 @@
#include "utils/string.hpp" #include "utils/string.hpp"
namespace repertory { namespace repertory {
auto event_level_from_string(std::string level) -> event_level { auto event_level_from_string(std::string level, event_level default_level)
-> event_level {
level = utils::string::to_lower(level); level = utils::string::to_lower(level);
if (level == "critical" || level == "event_level::critical") { if (level == "critical" || level == "event_level::critical") {
return event_level::critical; return event_level::critical;
@ -50,7 +51,7 @@ auto event_level_from_string(std::string level) -> event_level {
return event_level::trace; return event_level::trace;
} }
return event_level::info; return default_level;
} }
auto event_level_to_string(event_level level) -> std::string { auto event_level_to_string(event_level level) -> std::string {

Some files were not shown because too many files have changed in this diff Show More