Compare commits
42 Commits
v2.1.0-rc-
...
560ffbbb6a
Author | SHA1 | Date | |
---|---|---|---|
560ffbbb6a | |||
72314606f3 | |||
db009b69dd | |||
3ed99dc0ce | |||
762a7c99d5 | |||
4e62156b70 | |||
cc49536755 | |||
54b844dc3b | |||
1e8ba13f66 | |||
93011cee9c | |||
a474a5c73c | |||
17b98ca99d | |||
281eedb71e | |||
1ee533591c | |||
b87e1df140 | |||
f88239a13e | |||
68476cbc00 | |||
f2c1f64f02 | |||
a7209184c8 | |||
ba59e29499 | |||
f94196d865 | |||
bb5a9f9737 | |||
4bc5cf7c64 | |||
639d14452b | |||
e7413fb741 | |||
c0e720498d | |||
383c3b4be6 | |||
e9b202f5c8 | |||
bc3005a6a4 | |||
8cf19e0594 | |||
b137b57dbc | |||
5dff8927da | |||
197e79dd07 | |||
6262aca761 | |||
c156ae704b | |||
a67979ec40 | |||
54bfc11620 | |||
d33c2cd3a2 | |||
3a5f428fb6 | |||
0331152569 | |||
1b7e854f5f | |||
12a945d863 |
32
.clang-tidy
32
.clang-tidy
@ -1,38 +1,8 @@
|
||||
---
|
||||
Checks: 'clang-*,misc-unused-*,llvm-header-guard,llvm-include-order,modernize-*'
|
||||
Checks: '-*,clang-diagnostic-*,clang-analyzer-*,bugprone-*,concurrency-*,cppcoreguidelines-*,modernize-*,readability-*,-readability-redundant-access-specifiers,-readability-function-cognitive-complexity'
|
||||
WarningsAsErrors: ''
|
||||
HeaderFilterRegex: ''
|
||||
AnalyzeTemporaryDtors: false
|
||||
FormatStyle: none
|
||||
User: sgraves
|
||||
CheckOptions:
|
||||
- key: cert-dcl16-c.NewSuffixes
|
||||
value: 'L;LL;LU;LLU'
|
||||
- key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField
|
||||
value: '0'
|
||||
- key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors
|
||||
value: '1'
|
||||
- key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic
|
||||
value: '1'
|
||||
- key: google-readability-braces-around-statements.ShortStatementLines
|
||||
value: '1'
|
||||
- key: google-readability-function-size.StatementThreshold
|
||||
value: '800'
|
||||
- key: google-readability-namespace-comments.ShortNamespaceLines
|
||||
value: '10'
|
||||
- key: google-readability-namespace-comments.SpacesBeforeComments
|
||||
value: '2'
|
||||
- key: modernize-loop-convert.MaxCopySize
|
||||
value: '16'
|
||||
- key: modernize-loop-convert.MinConfidence
|
||||
value: reasonable
|
||||
- key: modernize-loop-convert.NamingStyle
|
||||
value: CamelCase
|
||||
- key: modernize-pass-by-value.IncludeStyle
|
||||
value: llvm
|
||||
- key: modernize-replace-auto-ptr.IncludeStyle
|
||||
value: llvm
|
||||
- key: modernize-use-nullptr.NullMacros
|
||||
value: 'NULL'
|
||||
...
|
||||
|
||||
|
@ -144,6 +144,7 @@ lptr
|
||||
lpwstr
|
||||
lzma
|
||||
makefiles
|
||||
markdownlint
|
||||
mbig
|
||||
mockwinfspdrive
|
||||
mqtt
|
||||
@ -157,6 +158,8 @@ nmake
|
||||
noappledouble
|
||||
nocache
|
||||
nocloseprocess
|
||||
nolintbegin
|
||||
nolintend
|
||||
nopath
|
||||
npubbytes
|
||||
ntfs
|
||||
@ -209,6 +212,7 @@ smatch
|
||||
sopen
|
||||
stbuf
|
||||
stdc
|
||||
stduuid
|
||||
stod
|
||||
stoi
|
||||
stoll
|
||||
@ -224,6 +228,7 @@ szlib_libpath
|
||||
target_precompile_headers
|
||||
teventsystem
|
||||
tolower
|
||||
tomykaira
|
||||
toolset
|
||||
ttmath
|
||||
ularge
|
||||
@ -254,6 +259,7 @@ woverloaded
|
||||
wpedantic
|
||||
wshadow
|
||||
wsign
|
||||
wunknown
|
||||
wunused
|
||||
wuseless
|
||||
xattr
|
||||
|
@ -6,7 +6,7 @@ pipeline {
|
||||
environment {
|
||||
BUILD_ARGS = '--build . -j 8'
|
||||
CONFIGURE_ARGS = '../.. -DCMAKE_BUILD_TYPE=Release -DREPERTORY_ENABLE_S3=ON'
|
||||
CONFIGURE_MINGW64_ARGS = '../.. -DCMAKE_BUILD_TYPE=Release -DREPERTORY_ENABLE_S3=ON -DCMAKE_TOOLCHAIN_FILE=../../cmake/mingw-w64-x86_64.cmake'
|
||||
CONFIGURE_MINGW64_ARGS = '../.. -DCMAKE_BUILD_TYPE=Release -DREPERTORY_ENABLE_S3=ON -DCMAKE_TOOLCHAIN_FILE=${WORKSPACE}/cmake/mingw-w64-x86_64.cmake'
|
||||
REPERTORY_TEST_DIR = "${HOME}/.ci/cfg"
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ pipeline {
|
||||
steps {
|
||||
retry(2) {
|
||||
sleep time: 5, unit: 'SECONDS'
|
||||
cmake arguments: '--build . -j 4', installation: 'InSearchPath', workingDir: 'build'
|
||||
cmake arguments: '--build . -j 3', installation: 'InSearchPath', workingDir: 'build'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,39 +0,0 @@
|
||||
#!groovy
|
||||
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
environment {
|
||||
REPERTORY_TEST_DIR = "C:\\.ci\\cfg"
|
||||
}
|
||||
|
||||
options {
|
||||
disableConcurrentBuilds()
|
||||
retry(2)
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('clean') {
|
||||
steps {
|
||||
bat 'del /q build\\Release\\librepertory.lib || exit 0'
|
||||
bat 'del /q build\\Release\\unittests.exe || exit 0'
|
||||
bat 'del /q build\\Release\\repertory.exe || exit 0'
|
||||
}
|
||||
}
|
||||
|
||||
stage('configure') {
|
||||
steps {
|
||||
cmake arguments: '.. -DCMAKE_BUILD_TYPE=Release -DREPERTORY_ENABLE_S3=ON', installation: 'InSearchPath', workingDir: 'build'
|
||||
}
|
||||
}
|
||||
|
||||
stage('build') {
|
||||
steps {
|
||||
retry(2) {
|
||||
sleep time: 5, unit: 'SECONDS'
|
||||
cmake arguments: '--build . --target ALL_BUILD --config Release -j 4', installation: 'InSearchPath', workingDir: 'build'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1248
3rd_party/cpp-httplib/httplib.h
vendored
1248
3rd_party/cpp-httplib/httplib.h
vendored
File diff suppressed because it is too large
Load Diff
876
3rd_party/stduuid/stduuid.h
vendored
Normal file
876
3rd_party/stduuid/stduuid.h
vendored
Normal file
@ -0,0 +1,876 @@
|
||||
#ifndef STDUUID_H
|
||||
#define STDUUID_H
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <array>
|
||||
#include <string_view>
|
||||
#include <iterator>
|
||||
#include <random>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include <optional>
|
||||
#include <chrono>
|
||||
#include <numeric>
|
||||
#include <atomic>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
|
||||
#define LIBUUID_CPP20_OR_GREATER
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef LIBUUID_CPP20_OR_GREATER
|
||||
#include <span>
|
||||
#else
|
||||
#include <gsl/span>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#ifdef UUID_SYSTEM_GENERATOR
|
||||
#include <objbase.h>
|
||||
#endif
|
||||
|
||||
#ifdef UUID_TIME_GENERATOR
|
||||
#include <iphlpapi.h>
|
||||
#pragma comment(lib, "IPHLPAPI.lib")
|
||||
#endif
|
||||
|
||||
#elif defined(__linux__) || defined(__unix__)
|
||||
|
||||
#ifdef UUID_SYSTEM_GENERATOR
|
||||
#include <uuid/uuid.h>
|
||||
#endif
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
#ifdef UUID_SYSTEM_GENERATOR
|
||||
#include <CoreFoundation/CFUUID.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
namespace uuids {
|
||||
#ifdef __cpp_lib_span
|
||||
template <class ElementType, std::size_t Extent>
|
||||
using span = std::span<ElementType, Extent>;
|
||||
#else
|
||||
template <class ElementType, std::ptrdiff_t Extent>
|
||||
using span = gsl::span<ElementType, Extent>;
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
template <typename TChar>
|
||||
[[nodiscard]] constexpr inline unsigned char hex2char(TChar const ch) noexcept {
|
||||
if (ch >= static_cast<TChar>('0') && ch <= static_cast<TChar>('9'))
|
||||
return static_cast<unsigned char>(ch - static_cast<TChar>('0'));
|
||||
if (ch >= static_cast<TChar>('a') && ch <= static_cast<TChar>('f'))
|
||||
return static_cast<unsigned char>(10 + ch - static_cast<TChar>('a'));
|
||||
if (ch >= static_cast<TChar>('A') && ch <= static_cast<TChar>('F'))
|
||||
return static_cast<unsigned char>(10 + ch - static_cast<TChar>('A'));
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
[[nodiscard]] constexpr inline bool is_hex(TChar const ch) noexcept {
|
||||
return (ch >= static_cast<TChar>('0') && ch <= static_cast<TChar>('9')) ||
|
||||
(ch >= static_cast<TChar>('a') && ch <= static_cast<TChar>('f')) ||
|
||||
(ch >= static_cast<TChar>('A') && ch <= static_cast<TChar>('F'));
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
[[nodiscard]] constexpr std::basic_string_view<TChar>
|
||||
to_string_view(TChar const *str) noexcept {
|
||||
if (str)
|
||||
return str;
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
[[nodiscard]] constexpr std::basic_string_view<typename StringType::value_type,
|
||||
typename StringType::traits_type>
|
||||
to_string_view(StringType const &str) noexcept {
|
||||
return str;
|
||||
}
|
||||
|
||||
class sha1 {
|
||||
public:
|
||||
using digest32_t = uint32_t[5];
|
||||
using digest8_t = uint8_t[20];
|
||||
|
||||
static constexpr unsigned int block_bytes = 64;
|
||||
|
||||
[[nodiscard]] inline static uint32_t
|
||||
left_rotate(uint32_t value, size_t const count) noexcept {
|
||||
return (value << count) ^ (value >> (32 - count));
|
||||
}
|
||||
|
||||
sha1() { reset(); }
|
||||
|
||||
void reset() noexcept {
|
||||
m_digest[0] = 0x67452301;
|
||||
m_digest[1] = 0xEFCDAB89;
|
||||
m_digest[2] = 0x98BADCFE;
|
||||
m_digest[3] = 0x10325476;
|
||||
m_digest[4] = 0xC3D2E1F0;
|
||||
m_blockByteIndex = 0;
|
||||
m_byteCount = 0;
|
||||
}
|
||||
|
||||
void process_byte(uint8_t octet) {
|
||||
this->m_block[this->m_blockByteIndex++] = octet;
|
||||
++this->m_byteCount;
|
||||
if (m_blockByteIndex == block_bytes) {
|
||||
this->m_blockByteIndex = 0;
|
||||
process_block();
|
||||
}
|
||||
}
|
||||
|
||||
void process_block(void const *const start, void const *const end) {
|
||||
const uint8_t *begin = static_cast<const uint8_t *>(start);
|
||||
const uint8_t *finish = static_cast<const uint8_t *>(end);
|
||||
while (begin != finish) {
|
||||
process_byte(*begin);
|
||||
begin++;
|
||||
}
|
||||
}
|
||||
|
||||
void process_bytes(void const *const data, size_t const len) {
|
||||
const uint8_t *block = static_cast<const uint8_t *>(data);
|
||||
process_block(block, block + len);
|
||||
}
|
||||
|
||||
uint32_t const *get_digest(digest32_t digest) {
|
||||
size_t const bitCount = this->m_byteCount * 8;
|
||||
process_byte(0x80);
|
||||
if (this->m_blockByteIndex > 56) {
|
||||
while (m_blockByteIndex != 0) {
|
||||
process_byte(0);
|
||||
}
|
||||
while (m_blockByteIndex < 56) {
|
||||
process_byte(0);
|
||||
}
|
||||
} else {
|
||||
while (m_blockByteIndex < 56) {
|
||||
process_byte(0);
|
||||
}
|
||||
}
|
||||
process_byte(0);
|
||||
process_byte(0);
|
||||
process_byte(0);
|
||||
process_byte(0);
|
||||
process_byte(static_cast<unsigned char>((bitCount >> 24) & 0xFF));
|
||||
process_byte(static_cast<unsigned char>((bitCount >> 16) & 0xFF));
|
||||
process_byte(static_cast<unsigned char>((bitCount >> 8) & 0xFF));
|
||||
process_byte(static_cast<unsigned char>((bitCount)&0xFF));
|
||||
|
||||
memcpy(digest, m_digest, 5 * sizeof(uint32_t));
|
||||
return digest;
|
||||
}
|
||||
|
||||
uint8_t const *get_digest_bytes(digest8_t digest) {
|
||||
digest32_t d32;
|
||||
get_digest(d32);
|
||||
size_t di = 0;
|
||||
digest[di++] = static_cast<uint8_t>(d32[0] >> 24);
|
||||
digest[di++] = static_cast<uint8_t>(d32[0] >> 16);
|
||||
digest[di++] = static_cast<uint8_t>(d32[0] >> 8);
|
||||
digest[di++] = static_cast<uint8_t>(d32[0] >> 0);
|
||||
|
||||
digest[di++] = static_cast<uint8_t>(d32[1] >> 24);
|
||||
digest[di++] = static_cast<uint8_t>(d32[1] >> 16);
|
||||
digest[di++] = static_cast<uint8_t>(d32[1] >> 8);
|
||||
digest[di++] = static_cast<uint8_t>(d32[1] >> 0);
|
||||
|
||||
digest[di++] = static_cast<uint8_t>(d32[2] >> 24);
|
||||
digest[di++] = static_cast<uint8_t>(d32[2] >> 16);
|
||||
digest[di++] = static_cast<uint8_t>(d32[2] >> 8);
|
||||
digest[di++] = static_cast<uint8_t>(d32[2] >> 0);
|
||||
|
||||
digest[di++] = static_cast<uint8_t>(d32[3] >> 24);
|
||||
digest[di++] = static_cast<uint8_t>(d32[3] >> 16);
|
||||
digest[di++] = static_cast<uint8_t>(d32[3] >> 8);
|
||||
digest[di++] = static_cast<uint8_t>(d32[3] >> 0);
|
||||
|
||||
digest[di++] = static_cast<uint8_t>(d32[4] >> 24);
|
||||
digest[di++] = static_cast<uint8_t>(d32[4] >> 16);
|
||||
digest[di++] = static_cast<uint8_t>(d32[4] >> 8);
|
||||
digest[di++] = static_cast<uint8_t>(d32[4] >> 0);
|
||||
|
||||
return digest;
|
||||
}
|
||||
|
||||
private:
|
||||
void process_block() {
|
||||
uint32_t w[80];
|
||||
for (size_t i = 0; i < 16; i++) {
|
||||
w[i] = static_cast<uint32_t>(m_block[i * 4 + 0] << 24);
|
||||
w[i] |= static_cast<uint32_t>(m_block[i * 4 + 1] << 16);
|
||||
w[i] |= static_cast<uint32_t>(m_block[i * 4 + 2] << 8);
|
||||
w[i] |= static_cast<uint32_t>(m_block[i * 4 + 3]);
|
||||
}
|
||||
for (size_t i = 16; i < 80; i++) {
|
||||
w[i] = left_rotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1);
|
||||
}
|
||||
|
||||
uint32_t a = m_digest[0];
|
||||
uint32_t b = m_digest[1];
|
||||
uint32_t c = m_digest[2];
|
||||
uint32_t d = m_digest[3];
|
||||
uint32_t e = m_digest[4];
|
||||
|
||||
for (std::size_t i = 0; i < 80; ++i) {
|
||||
uint32_t f = 0;
|
||||
uint32_t k = 0;
|
||||
|
||||
if (i < 20) {
|
||||
f = (b & c) | (~b & d);
|
||||
k = 0x5A827999;
|
||||
} else if (i < 40) {
|
||||
f = b ^ c ^ d;
|
||||
k = 0x6ED9EBA1;
|
||||
} else if (i < 60) {
|
||||
f = (b & c) | (b & d) | (c & d);
|
||||
k = 0x8F1BBCDC;
|
||||
} else {
|
||||
f = b ^ c ^ d;
|
||||
k = 0xCA62C1D6;
|
||||
}
|
||||
uint32_t temp = left_rotate(a, 5) + f + e + k + w[i];
|
||||
e = d;
|
||||
d = c;
|
||||
c = left_rotate(b, 30);
|
||||
b = a;
|
||||
a = temp;
|
||||
}
|
||||
|
||||
m_digest[0] += a;
|
||||
m_digest[1] += b;
|
||||
m_digest[2] += c;
|
||||
m_digest[3] += d;
|
||||
m_digest[4] += e;
|
||||
}
|
||||
|
||||
private:
|
||||
digest32_t m_digest;
|
||||
uint8_t m_block[64];
|
||||
size_t m_blockByteIndex;
|
||||
size_t m_byteCount;
|
||||
};
|
||||
|
||||
template <typename CharT>
|
||||
inline constexpr CharT empty_guid[37] = "00000000-0000-0000-0000-000000000000";
|
||||
|
||||
template <>
|
||||
inline constexpr wchar_t empty_guid<wchar_t>[37] =
|
||||
L"00000000-0000-0000-0000-000000000000";
|
||||
|
||||
template <typename CharT>
|
||||
inline constexpr CharT guid_encoder[17] = "0123456789abcdef";
|
||||
|
||||
template <>
|
||||
inline constexpr wchar_t guid_encoder<wchar_t>[17] = L"0123456789abcdef";
|
||||
} // namespace detail
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
// UUID format https://tools.ietf.org/html/rfc4122
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
// Field NDR Data Type Octet # Note
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
// time_low unsigned long 0 - 3 The low field
|
||||
// of the timestamp. time_mid unsigned short 4 - 5
|
||||
// The middle field of the timestamp.
|
||||
// time_hi_and_version unsigned short 6 - 7 The high
|
||||
// field of the timestamp multiplexed with the version number.
|
||||
// clock_seq_hi_and_reserved unsigned small 8 The high field of
|
||||
// the clock sequence multiplexed with the variant. clock_seq_low
|
||||
// unsigned small 9 The low field of the clock sequence. node
|
||||
// character 10 - 15 The spatially unique node identifier.
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | time_low |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | time_mid | time_hi_and_version |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |clk_seq_hi_res | clk_seq_low | node (0-1) |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | node (2-5) |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
// enumerations
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// indicated by a bit pattern in octet 8, marked with N in
|
||||
// xxxxxxxx-xxxx-xxxx-Nxxx-xxxxxxxxxxxx
|
||||
enum class uuid_variant {
|
||||
// NCS backward compatibility (with the obsolete Apollo Network Computing
|
||||
// System 1.5 UUID format) N bit pattern: 0xxx > the first 6 octets of the
|
||||
// UUID are a 48-bit timestamp (the number of 4 microsecond units of time
|
||||
// since 1 Jan 1980 UTC); > the next 2 octets are reserved; > the next octet
|
||||
// is the "address family"; > the final 7 octets are a 56-bit host ID in the
|
||||
// form specified by the address family
|
||||
ncs,
|
||||
|
||||
// RFC 4122/DCE 1.1
|
||||
// N bit pattern: 10xx
|
||||
// > big-endian byte order
|
||||
rfc,
|
||||
|
||||
// Microsoft Corporation backward compatibility
|
||||
// N bit pattern: 110x
|
||||
// > little endian byte order
|
||||
// > formely used in the Component Object Model (COM) library
|
||||
microsoft,
|
||||
|
||||
// reserved for possible future definition
|
||||
// N bit pattern: 111x
|
||||
reserved
|
||||
};
|
||||
|
||||
// indicated by a bit pattern in octet 6, marked with M in
|
||||
// xxxxxxxx-xxxx-Mxxx-xxxx-xxxxxxxxxxxx
|
||||
enum class uuid_version {
|
||||
none = 0, // only possible for nil or invalid uuids
|
||||
time_based = 1, // The time-based version specified in RFC 4122
|
||||
dce_security = 2, // DCE Security version, with embedded POSIX UIDs.
|
||||
name_based_md5 =
|
||||
3, // The name-based version specified in RFS 4122 with MD5 hashing
|
||||
random_number_based = 4, // The randomly or pseudo-randomly generated version
|
||||
// specified in RFS 4122
|
||||
name_based_sha1 =
|
||||
5 // The name-based version specified in RFS 4122 with SHA1 hashing
|
||||
};
|
||||
|
||||
// Forward declare uuid & to_string so that we can declare to_string as a friend
|
||||
// later.
|
||||
class uuid;
|
||||
template <class CharT = char, class Traits = std::char_traits<CharT>,
|
||||
class Allocator = std::allocator<CharT>>
|
||||
std::basic_string<CharT, Traits, Allocator> to_string(uuid const &id);
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
// uuid class
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
class uuid {
|
||||
public:
|
||||
using value_type = uint8_t;
|
||||
|
||||
constexpr uuid() noexcept = default;
|
||||
|
||||
uuid(value_type (&arr)[16]) noexcept {
|
||||
std::copy(std::cbegin(arr), std::cend(arr), std::begin(data));
|
||||
}
|
||||
|
||||
constexpr uuid(std::array<value_type, 16> const &arr) noexcept : data{arr} {}
|
||||
|
||||
explicit uuid(span<value_type, 16> bytes) {
|
||||
std::copy(std::cbegin(bytes), std::cend(bytes), std::begin(data));
|
||||
}
|
||||
|
||||
template <typename ForwardIterator>
|
||||
explicit uuid(ForwardIterator first, ForwardIterator last) {
|
||||
if (std::distance(first, last) == 16)
|
||||
std::copy(first, last, std::begin(data));
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr uuid_variant variant() const noexcept {
|
||||
if ((data[8] & 0x80) == 0x00)
|
||||
return uuid_variant::ncs;
|
||||
else if ((data[8] & 0xC0) == 0x80)
|
||||
return uuid_variant::rfc;
|
||||
else if ((data[8] & 0xE0) == 0xC0)
|
||||
return uuid_variant::microsoft;
|
||||
else
|
||||
return uuid_variant::reserved;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr uuid_version version() const noexcept {
|
||||
if ((data[6] & 0xF0) == 0x10)
|
||||
return uuid_version::time_based;
|
||||
else if ((data[6] & 0xF0) == 0x20)
|
||||
return uuid_version::dce_security;
|
||||
else if ((data[6] & 0xF0) == 0x30)
|
||||
return uuid_version::name_based_md5;
|
||||
else if ((data[6] & 0xF0) == 0x40)
|
||||
return uuid_version::random_number_based;
|
||||
else if ((data[6] & 0xF0) == 0x50)
|
||||
return uuid_version::name_based_sha1;
|
||||
else
|
||||
return uuid_version::none;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool is_nil() const noexcept {
|
||||
for (size_t i = 0; i < data.size(); ++i)
|
||||
if (data[i] != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void swap(uuid &other) noexcept { data.swap(other.data); }
|
||||
|
||||
[[nodiscard]] inline span<std::byte const, 16> as_bytes() const {
|
||||
return span<std::byte const, 16>(
|
||||
reinterpret_cast<std::byte const *>(data.data()), 16);
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
[[nodiscard]] constexpr static bool
|
||||
is_valid_uuid(StringType const &in_str) noexcept {
|
||||
auto str = detail::to_string_view(in_str);
|
||||
bool firstDigit = true;
|
||||
size_t hasBraces = 0;
|
||||
size_t index = 0;
|
||||
|
||||
if (str.empty())
|
||||
return false;
|
||||
|
||||
if (str.front() == '{')
|
||||
hasBraces = 1;
|
||||
if (hasBraces && str.back() != '}')
|
||||
return false;
|
||||
|
||||
for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) {
|
||||
if (str[i] == '-')
|
||||
continue;
|
||||
|
||||
if (index >= 16 || !detail::is_hex(str[i])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (firstDigit) {
|
||||
firstDigit = false;
|
||||
} else {
|
||||
index++;
|
||||
firstDigit = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (index < 16) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename StringType>
|
||||
[[nodiscard]] constexpr static std::optional<uuid>
|
||||
from_string(StringType const &in_str) noexcept {
|
||||
auto str = detail::to_string_view(in_str);
|
||||
bool firstDigit = true;
|
||||
size_t hasBraces = 0;
|
||||
size_t index = 0;
|
||||
|
||||
std::array<uint8_t, 16> data{{0}};
|
||||
|
||||
if (str.empty())
|
||||
return {};
|
||||
|
||||
if (str.front() == '{')
|
||||
hasBraces = 1;
|
||||
if (hasBraces && str.back() != '}')
|
||||
return {};
|
||||
|
||||
for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) {
|
||||
if (str[i] == '-')
|
||||
continue;
|
||||
|
||||
if (index >= 16 || !detail::is_hex(str[i])) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (firstDigit) {
|
||||
data[index] = static_cast<uint8_t>(detail::hex2char(str[i]) << 4);
|
||||
firstDigit = false;
|
||||
} else {
|
||||
data[index] =
|
||||
static_cast<uint8_t>(data[index] | detail::hex2char(str[i]));
|
||||
index++;
|
||||
firstDigit = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (index < 16) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return uuid{data};
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<value_type, 16> data{{0}};
|
||||
|
||||
friend bool operator==(uuid const &lhs, uuid const &rhs) noexcept;
|
||||
friend bool operator<(uuid const &lhs, uuid const &rhs) noexcept;
|
||||
|
||||
template <class Elem, class Traits>
|
||||
friend std::basic_ostream<Elem, Traits> &
|
||||
operator<<(std::basic_ostream<Elem, Traits> &s, uuid const &id);
|
||||
|
||||
template <class CharT, class Traits, class Allocator>
|
||||
friend std::basic_string<CharT, Traits, Allocator> to_string(uuid const &id);
|
||||
|
||||
friend std::hash<uuid>;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
// operators and non-member functions
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
[[nodiscard]] inline bool operator==(uuid const &lhs,
|
||||
uuid const &rhs) noexcept {
|
||||
return lhs.data == rhs.data;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool operator!=(uuid const &lhs,
|
||||
uuid const &rhs) noexcept {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool operator<(uuid const &lhs, uuid const &rhs) noexcept {
|
||||
return lhs.data < rhs.data;
|
||||
}
|
||||
|
||||
template <class CharT, class Traits, class Allocator>
|
||||
[[nodiscard]] inline std::basic_string<CharT, Traits, Allocator>
|
||||
to_string(uuid const &id) {
|
||||
std::basic_string<CharT, Traits, Allocator> uustr{detail::empty_guid<CharT>};
|
||||
|
||||
for (size_t i = 0, index = 0; i < 36; ++i) {
|
||||
if (i == 8 || i == 13 || i == 18 || i == 23) {
|
||||
continue;
|
||||
}
|
||||
uustr[i] = detail::guid_encoder<CharT>[id.data[index] >> 4 & 0x0f];
|
||||
uustr[++i] = detail::guid_encoder<CharT>[id.data[index] & 0x0f];
|
||||
index++;
|
||||
}
|
||||
|
||||
return uustr;
|
||||
}
|
||||
|
||||
template <class Elem, class Traits>
|
||||
std::basic_ostream<Elem, Traits> &
|
||||
operator<<(std::basic_ostream<Elem, Traits> &s, uuid const &id) {
|
||||
s << to_string(id);
|
||||
return s;
|
||||
}
|
||||
|
||||
inline void swap(uuids::uuid &lhs, uuids::uuid &rhs) noexcept { lhs.swap(rhs); }
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
// namespace IDs that could be used for generating name-based uuids
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// Name string is a fully-qualified domain name
|
||||
static uuid uuid_namespace_dns{{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1,
|
||||
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
|
||||
0xc8}};
|
||||
|
||||
// Name string is a URL
|
||||
static uuid uuid_namespace_url{{0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1,
|
||||
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
|
||||
0xc8}};
|
||||
|
||||
// Name string is an ISO OID (See https://oidref.com/,
|
||||
// https://en.wikipedia.org/wiki/Object_identifier)
|
||||
static uuid uuid_namespace_oid{{0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1,
|
||||
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
|
||||
0xc8}};
|
||||
|
||||
// Name string is an X.500 DN, in DER or a text output format (See
|
||||
// https://en.wikipedia.org/wiki/X.500,
|
||||
// https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One)
|
||||
static uuid uuid_namespace_x500{{0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1,
|
||||
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
|
||||
0xc8}};
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
// uuid generators
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#ifdef UUID_SYSTEM_GENERATOR
|
||||
class uuid_system_generator {
|
||||
public:
|
||||
using result_type = uuid;
|
||||
|
||||
uuid operator()() {
|
||||
#ifdef _WIN32
|
||||
|
||||
GUID newId;
|
||||
HRESULT hr = ::CoCreateGuid(&newId);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
throw std::system_error(hr, std::system_category(),
|
||||
"CoCreateGuid failed");
|
||||
}
|
||||
|
||||
std::array<uint8_t, 16> bytes = {
|
||||
{static_cast<unsigned char>((newId.Data1 >> 24) & 0xFF),
|
||||
static_cast<unsigned char>((newId.Data1 >> 16) & 0xFF),
|
||||
static_cast<unsigned char>((newId.Data1 >> 8) & 0xFF),
|
||||
static_cast<unsigned char>((newId.Data1) & 0xFF),
|
||||
|
||||
(unsigned char)((newId.Data2 >> 8) & 0xFF),
|
||||
(unsigned char)((newId.Data2) & 0xFF),
|
||||
|
||||
(unsigned char)((newId.Data3 >> 8) & 0xFF),
|
||||
(unsigned char)((newId.Data3) & 0xFF),
|
||||
|
||||
newId.Data4[0], newId.Data4[1], newId.Data4[2], newId.Data4[3],
|
||||
newId.Data4[4], newId.Data4[5], newId.Data4[6], newId.Data4[7]}};
|
||||
|
||||
return uuid{std::begin(bytes), std::end(bytes)};
|
||||
|
||||
#elif defined(__linux__) || defined(__unix__)
|
||||
|
||||
uuid_t id;
|
||||
uuid_generate(id);
|
||||
|
||||
std::array<uint8_t, 16> bytes = {{id[0], id[1], id[2], id[3], id[4], id[5],
|
||||
id[6], id[7], id[8], id[9], id[10],
|
||||
id[11], id[12], id[13], id[14], id[15]}};
|
||||
|
||||
return uuid{std::begin(bytes), std::end(bytes)};
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
auto newId = CFUUIDCreate(NULL);
|
||||
auto bytes = CFUUIDGetUUIDBytes(newId);
|
||||
CFRelease(newId);
|
||||
|
||||
std::array<uint8_t, 16> arrbytes = {
|
||||
{bytes.byte0, bytes.byte1, bytes.byte2, bytes.byte3, bytes.byte4,
|
||||
bytes.byte5, bytes.byte6, bytes.byte7, bytes.byte8, bytes.byte9,
|
||||
bytes.byte10, bytes.byte11, bytes.byte12, bytes.byte13, bytes.byte14,
|
||||
bytes.byte15}};
|
||||
return uuid{std::begin(arrbytes), std::end(arrbytes)};
|
||||
#else
|
||||
return uuid{};
|
||||
#endif
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename UniformRandomNumberGenerator>
|
||||
class basic_uuid_random_generator {
|
||||
public:
|
||||
using engine_type = UniformRandomNumberGenerator;
|
||||
|
||||
explicit basic_uuid_random_generator(engine_type &gen)
|
||||
: generator(&gen, [](auto) {}) {}
|
||||
explicit basic_uuid_random_generator(engine_type *gen)
|
||||
: generator(gen, [](auto) {}) {}
|
||||
|
||||
[[nodiscard]] uuid operator()() {
|
||||
alignas(uint32_t) uint8_t bytes[16];
|
||||
for (int i = 0; i < 16; i += 4)
|
||||
*reinterpret_cast<uint32_t *>(bytes + i) = distribution(*generator);
|
||||
|
||||
// variant must be 10xxxxxx
|
||||
bytes[8] &= 0xBF;
|
||||
bytes[8] |= 0x80;
|
||||
|
||||
// version must be 0100xxxx
|
||||
bytes[6] &= 0x4F;
|
||||
bytes[6] |= 0x40;
|
||||
|
||||
return uuid{std::begin(bytes), std::end(bytes)};
|
||||
}
|
||||
|
||||
private:
|
||||
std::uniform_int_distribution<uint32_t> distribution;
|
||||
std::shared_ptr<UniformRandomNumberGenerator> generator;
|
||||
};
|
||||
|
||||
using uuid_random_generator = basic_uuid_random_generator<std::mt19937>;
|
||||
|
||||
class uuid_name_generator {
|
||||
public:
|
||||
explicit uuid_name_generator(uuid const &namespace_uuid) noexcept
|
||||
: nsuuid(namespace_uuid) {}
|
||||
|
||||
template <typename StringType>
|
||||
[[nodiscard]] uuid operator()(StringType const &name) {
|
||||
reset();
|
||||
process_characters(detail::to_string_view(name));
|
||||
return make_uuid();
|
||||
}
|
||||
|
||||
private:
|
||||
void reset() {
|
||||
hasher.reset();
|
||||
std::byte bytes[16];
|
||||
auto nsbytes = nsuuid.as_bytes();
|
||||
std::copy(std::cbegin(nsbytes), std::cend(nsbytes), bytes);
|
||||
hasher.process_bytes(bytes, 16);
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
void process_characters(std::basic_string_view<CharT, Traits> const str) {
|
||||
for (uint32_t c : str) {
|
||||
hasher.process_byte(static_cast<uint8_t>(c & 0xFF));
|
||||
if constexpr (!std::is_same_v<CharT, char>) {
|
||||
hasher.process_byte(static_cast<uint8_t>((c >> 8) & 0xFF));
|
||||
hasher.process_byte(static_cast<uint8_t>((c >> 16) & 0xFF));
|
||||
hasher.process_byte(static_cast<uint8_t>((c >> 24) & 0xFF));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] uuid make_uuid() {
|
||||
detail::sha1::digest8_t digest;
|
||||
hasher.get_digest_bytes(digest);
|
||||
|
||||
// variant must be 0b10xxxxxx
|
||||
digest[8] &= 0xBF;
|
||||
digest[8] |= 0x80;
|
||||
|
||||
// version must be 0b0101xxxx
|
||||
digest[6] &= 0x5F;
|
||||
digest[6] |= 0x50;
|
||||
|
||||
return uuid{digest, digest + 16};
|
||||
}
|
||||
|
||||
private:
|
||||
uuid nsuuid;
|
||||
detail::sha1 hasher;
|
||||
};
|
||||
|
||||
#ifdef UUID_TIME_GENERATOR
|
||||
// !!! DO NOT USE THIS IN PRODUCTION
|
||||
// this implementation is unreliable for good uuids
|
||||
class uuid_time_generator {
|
||||
using mac_address = std::array<unsigned char, 6>;
|
||||
|
||||
std::optional<mac_address> device_address;
|
||||
|
||||
[[nodiscard]] bool get_mac_address() {
|
||||
if (device_address.has_value()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
DWORD len = 0;
|
||||
auto ret = GetAdaptersInfo(nullptr, &len);
|
||||
if (ret != ERROR_BUFFER_OVERFLOW)
|
||||
return false;
|
||||
std::vector<unsigned char> buf(len);
|
||||
auto pips = reinterpret_cast<PIP_ADAPTER_INFO>(&buf.front());
|
||||
ret = GetAdaptersInfo(pips, &len);
|
||||
if (ret != ERROR_SUCCESS)
|
||||
return false;
|
||||
mac_address addr;
|
||||
std::copy(pips->Address, pips->Address + 6, std::begin(addr));
|
||||
device_address = addr;
|
||||
#endif
|
||||
|
||||
return device_address.has_value();
|
||||
}
|
||||
|
||||
[[nodiscard]] long long get_time_intervals() {
|
||||
auto start = std::chrono::system_clock::from_time_t(time_t(-12219292800));
|
||||
auto diff = std::chrono::system_clock::now() - start;
|
||||
auto ns =
|
||||
std::chrono::duration_cast<std::chrono::nanoseconds>(diff).count();
|
||||
return ns / 100;
|
||||
}
|
||||
|
||||
[[nodiscard]] static unsigned short get_clock_sequence() {
|
||||
static std::mt19937 clock_gen(std::random_device{}());
|
||||
static std::uniform_int_distribution<unsigned short> clock_dis;
|
||||
static std::atomic_ushort clock_sequence = clock_dis(clock_gen);
|
||||
return clock_sequence++;
|
||||
}
|
||||
|
||||
public:
|
||||
[[nodiscard]] uuid operator()() {
|
||||
if (get_mac_address()) {
|
||||
std::array<uuids::uuid::value_type, 16> data;
|
||||
|
||||
auto tm = get_time_intervals();
|
||||
|
||||
auto clock_seq = get_clock_sequence();
|
||||
|
||||
auto ptm = reinterpret_cast<uuids::uuid::value_type *>(&tm);
|
||||
|
||||
memcpy(&data[0], ptm + 4, 4);
|
||||
memcpy(&data[4], ptm + 2, 2);
|
||||
memcpy(&data[6], ptm, 2);
|
||||
|
||||
memcpy(&data[8], &clock_seq, 2);
|
||||
|
||||
// variant must be 0b10xxxxxx
|
||||
data[8] &= 0xBF;
|
||||
data[8] |= 0x80;
|
||||
|
||||
// version must be 0b0001xxxx
|
||||
data[6] &= 0x1F;
|
||||
data[6] |= 0x10;
|
||||
|
||||
memcpy(&data[10], &device_address.value()[0], 6);
|
||||
|
||||
return uuids::uuid{std::cbegin(data), std::cend(data)};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
};
|
||||
#endif
|
||||
} // namespace uuids
|
||||
|
||||
namespace std {
|
||||
template <> struct hash<uuids::uuid> {
|
||||
using argument_type = uuids::uuid;
|
||||
using result_type = std::size_t;
|
||||
|
||||
[[nodiscard]] result_type operator()(argument_type const &uuid) const {
|
||||
#ifdef UUID_HASH_STRING_BASED
|
||||
std::hash<std::string> hasher;
|
||||
return static_cast<result_type>(hasher(uuids::to_string(uuid)));
|
||||
#else
|
||||
uint64_t l = static_cast<uint64_t>(uuid.data[0]) << 56 |
|
||||
static_cast<uint64_t>(uuid.data[1]) << 48 |
|
||||
static_cast<uint64_t>(uuid.data[2]) << 40 |
|
||||
static_cast<uint64_t>(uuid.data[3]) << 32 |
|
||||
static_cast<uint64_t>(uuid.data[4]) << 24 |
|
||||
static_cast<uint64_t>(uuid.data[5]) << 16 |
|
||||
static_cast<uint64_t>(uuid.data[6]) << 8 |
|
||||
static_cast<uint64_t>(uuid.data[7]);
|
||||
uint64_t h = static_cast<uint64_t>(uuid.data[8]) << 56 |
|
||||
static_cast<uint64_t>(uuid.data[9]) << 48 |
|
||||
static_cast<uint64_t>(uuid.data[10]) << 40 |
|
||||
static_cast<uint64_t>(uuid.data[11]) << 32 |
|
||||
static_cast<uint64_t>(uuid.data[12]) << 24 |
|
||||
static_cast<uint64_t>(uuid.data[13]) << 16 |
|
||||
static_cast<uint64_t>(uuid.data[14]) << 8 |
|
||||
static_cast<uint64_t>(uuid.data[15]);
|
||||
|
||||
if constexpr (sizeof(result_type) > 4) {
|
||||
return result_type(l ^ h);
|
||||
} else {
|
||||
uint64_t hash64 = l ^ h;
|
||||
return result_type(uint32_t(hash64 >> 32) ^ uint32_t(hash64));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
#endif /* STDUUID_H */
|
17
CHANGELOG.md
17
CHANGELOG.md
@ -1,7 +1,24 @@
|
||||
# Changelog
|
||||
|
||||
## 2.0.1-rc
|
||||
|
||||
### Issues
|
||||
|
||||
* \#10 Address compiler warnings
|
||||
|
||||
### Changes from v2.0.0-rc
|
||||
|
||||
* Refactored S3 provider
|
||||
* Require `c++20`
|
||||
* Removed MSVC compilation support (MinGW-64 should be used)
|
||||
* Upgraded `boost` to v1.83.0
|
||||
* Upgraded `curl` to v8.4.0
|
||||
* Upgraded `libsodium` to v1.0.19
|
||||
* Upgraded `rocksdb` to v8.6.7
|
||||
|
||||
## 2.0.0-rc
|
||||
|
||||
<!-- markdownlint-disable-next-line -->
|
||||
### Issues
|
||||
|
||||
* \#1 \[bug\] Unable to mount S3 due to 'item_not_found' exception
|
||||
|
@ -11,7 +11,7 @@ include(ExternalProject)
|
||||
|
||||
set(REPERTORY_MAJOR 2)
|
||||
set(REPERTORY_MINOR 0)
|
||||
set(REPERTORY_REV 0)
|
||||
set(REPERTORY_REV 1)
|
||||
set(REPERTORY_RELEASE_NUM 0)
|
||||
set(REPERTORY_RELEASE_ITER rc)
|
||||
set(REPERTORY_VERSION ${REPERTORY_MAJOR}.${REPERTORY_MINOR}.${REPERTORY_REV}-${REPERTORY_RELEASE_ITER})
|
||||
@ -44,17 +44,6 @@ if (UNIX)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (MSVC OR MINGW)
|
||||
set(WINFSP_LIBRARY_BASENAME winfsp-x64)
|
||||
|
||||
include_directories(SYSTEM ${CMAKE_SOURCE_DIR}/3rd_party/winfsp-${WINFSP_VERSION}/inc)
|
||||
link_directories(${CMAKE_SOURCE_DIR}/3rd_party/winfsp-${WINFSP_VERSION}/lib)
|
||||
set(REPERTORY_LINK_LIBRARIES
|
||||
${REPERTORY_LINK_LIBRARIES}
|
||||
${WINFSP_LIBRARY_BASENAME}.lib
|
||||
)
|
||||
endif()
|
||||
|
||||
if (LINUX OR MINGW)
|
||||
if (CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.0)
|
||||
message(FATAL_ERROR "Require at least gcc-8.0")
|
||||
@ -163,27 +152,20 @@ elseif (MACOS)
|
||||
"-framework SystemConfiguration"
|
||||
)
|
||||
elseif (MSVC)
|
||||
set(OPENSSL_USE_STATIC_LIBS TRUE)
|
||||
if (NOT OPENSSL_ROOT_DIR)
|
||||
set (OPENSSL_ROOT_DIR "$ENV{USERPROFILE}\\scoop\\apps\\openssl\\current")
|
||||
endif()
|
||||
find_package(OpenSSL 1.1.1 REQUIRED)
|
||||
set(OPENSSL_LIBRARIES OpenSSL::SSL OpenSSL::Crypto)
|
||||
set(REPERTORY_DEFINITIONS ${REPERTORY_DEFINITIONS} -D_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING)
|
||||
|
||||
if (NOT CMAKE_GENERATOR_LOWER STREQUAL "nmake makefiles")
|
||||
set(REPERTORY_OUTPUT_DIR ${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE})
|
||||
endif()
|
||||
message(FATAL_ERROR "MSVC is currently not supported [MinGW-64 should be used]")
|
||||
endif()
|
||||
|
||||
if (MINGW)
|
||||
set(WINFSP_LIBRARY_BASENAME winfsp-x64)
|
||||
|
||||
include_directories(SYSTEM ${CMAKE_SOURCE_DIR}/3rd_party/winfsp-${WINFSP_VERSION}/inc)
|
||||
link_directories(${CMAKE_SOURCE_DIR}/3rd_party/winfsp-${WINFSP_VERSION}/lib)
|
||||
set(REPERTORY_LINK_LIBRARIES
|
||||
${REPERTORY_LINK_LIBRARIES}
|
||||
${WINFSP_LIBRARY_BASENAME}.lib
|
||||
mswsock
|
||||
)
|
||||
endif()
|
||||
|
||||
if (MSVC OR MINGW)
|
||||
set(REPERTORY_VER_FILEVERSION ${REPERTORY_MAJOR},${REPERTORY_MINOR},${REPERTORY_REV},${REPERTORY_RELEASE_NUM})
|
||||
set(REPERTORY_VER_FILEVERSION_STR ${REPERTORY_MAJOR}.${REPERTORY_MINOR}.${REPERTORY_REV}.${REPERTORY_RELEASE_NUM})
|
||||
set(REPERTORY_VER_PRODUCTVERSION ${REPERTORY_MAJOR},${REPERTORY_MINOR},${REPERTORY_REV},${REPERTORY_RELEASE_NUM})
|
||||
@ -195,10 +177,6 @@ if (MSVC OR MINGW)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.rc.in ${CMAKE_CURRENT_SOURCE_DIR}/src/version.rc @ONLY)
|
||||
set(WINDOWS_VERSION_RC ${CMAKE_CURRENT_SOURCE_DIR}/src/version.rc)
|
||||
|
||||
if (MSVC)
|
||||
set(LIB_EXT .lib)
|
||||
endif()
|
||||
|
||||
set(REPERTORY_LINK_LIBRARIES
|
||||
${REPERTORY_LINK_LIBRARIES}
|
||||
advapi32${LIB_EXT}
|
||||
@ -239,20 +217,21 @@ include(cmake/zlib.cmake)
|
||||
include(cmake/openssl.cmake)
|
||||
include(cmake/curl.cmake)
|
||||
include(cmake/boost.cmake)
|
||||
include(cmake/libuuid.cmake)
|
||||
include(cmake/rocksdb.cmake)
|
||||
include(cmake/libsodium.cmake)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/common.cpp.in ${CMAKE_CURRENT_SOURCE_DIR}/src/common.cpp @ONLY)
|
||||
|
||||
include_directories(include)
|
||||
include_directories(SYSTEM
|
||||
${Boost_INCLUDE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/3rd_party/cpp-httplib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/3rd_party/stduuid
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/3rd_party/json
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/3rd_party/pugixml/src
|
||||
${CURL_INCLUDE_DIRS}
|
||||
${LIBFUSE2_INCLUDE_DIRS}
|
||||
${LIBFUSE3_INCLUDE_DIRS}
|
||||
${LIBUUID_INCLUDE_DIR}
|
||||
${OPENSSL_INCLUDE_DIR}
|
||||
${ROCKSDB_INCLUDE_DIRS}
|
||||
)
|
||||
@ -261,7 +240,6 @@ set(REPERTORY_LINK_LIBRARIES
|
||||
${ROCKSDB_LIBRARIES}
|
||||
${LIBFUSE2_LIBRARIES}
|
||||
${LIBFUSE3_LIBRARIES}
|
||||
${LIBUUID_LIBRARIES}
|
||||
${Boost_LIBRARIES}
|
||||
${CURL_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES}
|
||||
@ -287,8 +265,6 @@ file(GLOB_RECURSE REPERTORY_SOURCES
|
||||
)
|
||||
list(REMOVE_ITEM REPERTORY_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/common.cpp.in ${CMAKE_CURRENT_SOURCE_DIR}/src/common.cpp @ONLY)
|
||||
|
||||
include(cmake/helpers.cmake)
|
||||
include(cmake/librepertory.cmake)
|
||||
include(cmake/repertory.cmake)
|
||||
|
@ -47,6 +47,7 @@ on Windows.
|
||||
* [RocksDB](https://rocksdb.org/)
|
||||
* [ScPrime](https://scpri.me/)
|
||||
* [Sia Decentralized Cloud Storage](https://sia.tech/)
|
||||
* [stduuid](https://github.com/mariusbancila/stduuid)
|
||||
* [WinFSP - FUSE for Windows](https://github.com/billziss-gh/winfsp)
|
||||
* [zlib](https://zlib.net/)
|
||||
|
||||
|
@ -2,136 +2,91 @@ set(BOOST_PROJECT_NAME boost_${BOOST_VERSION})
|
||||
set(BOOST_BUILD_ROOT ${EXTERNAL_BUILD_ROOT}/builds/${BOOST_PROJECT_NAME})
|
||||
|
||||
set(BOOST_ADDRESS_MODEL 64)
|
||||
set(BOOST_DLL_ARCH x64)
|
||||
set(BOOST_DOWNLOAD_URL https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source/boost_${BOOST_VERSION_DL}.tar.gz)
|
||||
set(BOOST_VERSION ${BOOST_MAJOR_VERSION}.${BOOST_MINOR_VERSION}.${BOOST_REVISION})
|
||||
set(BOOST_VERSION2 ${BOOST_MAJOR_VERSION}_${BOOST_MINOR_VERSION}_${BOOST_REVISION})
|
||||
|
||||
if (UNIX OR MINGW)
|
||||
if (IS_CLANG_COMPILER)
|
||||
set(BOOST_TOOLSET --with-toolset=clang)
|
||||
else ()
|
||||
set(BOOST_OPENSSL_DIR "--openssldir=${EXTERNAL_BUILD_ROOT}")
|
||||
endif()
|
||||
set(BOOST_DOWNLOAD_URL https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source/boost_${BOOST_VERSION2}.tar.gz)
|
||||
|
||||
if (IS_ARM64)
|
||||
set (BOOST_ARCH arm)
|
||||
else()
|
||||
set (BOOST_ARCH x86)
|
||||
endif()
|
||||
|
||||
set (BOOST_COMMON_ARGS
|
||||
${BOOST_OPENSSL_DIR}
|
||||
--prefix=${EXTERNAL_BUILD_ROOT}
|
||||
address-model=${BOOST_ADDRESS_MODEL}
|
||||
architecture=${BOOST_ARCH}
|
||||
cxxflags=-std=c++${CMAKE_CXX_STANDARD}
|
||||
cxxstd=${CMAKE_CXX_STANDARD}
|
||||
define=BOOST_ASIO_HAS_STD_STRING_VIEW
|
||||
define=BOOST_SYSTEM_NO_DEPRECATED
|
||||
link=static
|
||||
linkflags=-std=c++${CMAKE_CXX_STANDARD}
|
||||
threading=multi
|
||||
variant=${CMAKE_BUILD_TYPE_LOWER}
|
||||
)
|
||||
|
||||
if (MINGW)
|
||||
set(BOOST_COMMON_ARGS
|
||||
${BOOST_COMMON_ARGS}
|
||||
--user-config=./user-config.jam
|
||||
)
|
||||
set(BOOST_TARGET_OS target-os=windows)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(boost_project
|
||||
DOWNLOAD_NO_PROGRESS 1
|
||||
URL ${BOOST_DOWNLOAD_URL}
|
||||
PREFIX ${BOOST_BUILD_ROOT}
|
||||
BUILD_IN_SOURCE 1
|
||||
CONFIGURE_COMMAND
|
||||
cp -f ${CMAKE_CURRENT_SOURCE_DIR}/3rd_party/user-config.jam . &&
|
||||
./bootstrap.sh
|
||||
${BOOST_TOOLSET}
|
||||
${BOOST_TARGET_OS}
|
||||
--with-libraries=atomic,chrono,date_time,filesystem,random,regex,serialization,system,thread
|
||||
BUILD_COMMAND
|
||||
./b2
|
||||
${BOOST_COMMON_ARGS}
|
||||
${BOOST_TARGET_OS}
|
||||
INSTALL_COMMAND
|
||||
./b2
|
||||
${BOOST_COMMON_ARGS}
|
||||
${BOOST_TARGET_OS}
|
||||
install
|
||||
)
|
||||
|
||||
add_dependencies(boost_project openssl_project)
|
||||
|
||||
set(BOOST_ROOT ${BOOST_BUILD_ROOT}/src/boost_project)
|
||||
if (MINGW)
|
||||
set(BOOST_GCC_VERSION ${CMAKE_CXX_COMPILER_VERSION})
|
||||
string(REPLACE "." ";" BOOST_GCC_VERSION_LIST ${BOOST_GCC_VERSION})
|
||||
list(GET BOOST_GCC_VERSION_LIST 0 BOOST_GCC_MAJOR_VERSION)
|
||||
# set(BOOST_LIB_EXTRA "-mgw${BOOST_GCC_MAJOR_VERSION}-mt-x64-${BOOST_MAJOR_VERSION}_${BOOST_MINOR_VERSION}")
|
||||
endif()
|
||||
|
||||
set(Boost_LIBRARIES
|
||||
libboost_system${BOOST_LIB_EXTRA}.a
|
||||
libboost_atomic${BOOST_LIB_EXTRA}.a
|
||||
libboost_chrono${BOOST_LIB_EXTRA}.a
|
||||
libboost_date_time${BOOST_LIB_EXTRA}.a
|
||||
libboost_filesystem${BOOST_LIB_EXTRA}.a
|
||||
libboost_random${BOOST_LIB_EXTRA}.a
|
||||
libboost_regex${BOOST_LIB_EXTRA}.a
|
||||
libboost_serialization${BOOST_LIB_EXTRA}.a
|
||||
libboost_thread${BOOST_LIB_EXTRA}.a
|
||||
)
|
||||
elseif(MSVC)
|
||||
set (BOOST_COMMON_ARGS
|
||||
--with-date_time
|
||||
--with-regex
|
||||
--with-serialization
|
||||
--with-system
|
||||
--with-filesystem
|
||||
--prefix=${EXTERNAL_BUILD_ROOT}
|
||||
runtime-link=shared
|
||||
threading=multi
|
||||
address-model=${BOOST_ADDRESS_MODEL}
|
||||
architecture=x86
|
||||
toolset=${BOOST_MSVC_TOOLSET}
|
||||
variant=${CMAKE_BUILD_TYPE_LOWER}
|
||||
-sZLIB_BINARY=zlibstatic${DEBUG_EXTRA}
|
||||
-sZLIB_LIBPATH="${EXTERNAL_BUILD_ROOT}/lib"
|
||||
-sZLIB_INCLUDE="${EXTERNAL_BUILD_ROOT}/include"
|
||||
)
|
||||
|
||||
ExternalProject_Add(boost_project
|
||||
DOWNLOAD_NO_PROGRESS 1
|
||||
URL ${BOOST_DOWNLOAD_URL}
|
||||
PREFIX ${BOOST_BUILD_ROOT}
|
||||
BUILD_IN_SOURCE 1
|
||||
CONFIGURE_COMMAND
|
||||
bootstrap.bat
|
||||
--with-date_time
|
||||
--with-regex
|
||||
--with-system
|
||||
--with-serialization
|
||||
--with-filesystem
|
||||
BUILD_COMMAND
|
||||
b2.exe
|
||||
${BOOST_COMMON_ARGS}
|
||||
INSTALL_COMMAND
|
||||
b2.exe
|
||||
install
|
||||
${BOOST_COMMON_ARGS}
|
||||
)
|
||||
|
||||
add_dependencies(boost_project zlib_project)
|
||||
set(BOOST_ROOT ${BOOST_BUILD_ROOT}/src/boost_project)
|
||||
set(Boost_INCLUDE_DIR ${EXTERNAL_BUILD_ROOT}/include/boost-${BOOST_VERSION_DLL})
|
||||
set(Boost_LIBRARIES
|
||||
${EXTERNAL_BUILD_ROOT}/lib/libboost_date_time-vc${BOOST_MSVC_TOOLSET_DLL}-mt-${BOOST_DEBUG_EXTRA}${BOOST_DLL_ARCH}-${BOOST_VERSION_DLL}.lib
|
||||
${EXTERNAL_BUILD_ROOT}/lib/libboost_filesystem-vc${BOOST_MSVC_TOOLSET_DLL}-mt-${BOOST_DEBUG_EXTRA}${BOOST_DLL_ARCH}-${BOOST_VERSION_DLL}.lib
|
||||
${EXTERNAL_BUILD_ROOT}/lib/libboost_regex-vc${BOOST_MSVC_TOOLSET_DLL}-mt-${BOOST_DEBUG_EXTRA}${BOOST_DLL_ARCH}-${BOOST_VERSION_DLL}.lib
|
||||
${EXTERNAL_BUILD_ROOT}/lib/libboost_serialization-vc${BOOST_MSVC_TOOLSET_DLL}-mt-${BOOST_DEBUG_EXTRA}${BOOST_DLL_ARCH}-${BOOST_VERSION_DLL}.lib
|
||||
${EXTERNAL_BUILD_ROOT}/lib/libboost_system-vc${BOOST_MSVC_TOOLSET_DLL}-mt-${BOOST_DEBUG_EXTRA}${BOOST_DLL_ARCH}-${BOOST_VERSION_DLL}.lib
|
||||
)
|
||||
if (IS_CLANG_COMPILER)
|
||||
set(BOOST_TOOLSET --with-toolset=clang)
|
||||
else ()
|
||||
set(BOOST_OPENSSL_DIR "--openssldir=${EXTERNAL_BUILD_ROOT}")
|
||||
endif()
|
||||
|
||||
if (IS_ARM64)
|
||||
set (BOOST_ARCH arm)
|
||||
else()
|
||||
set (BOOST_ARCH x86)
|
||||
endif()
|
||||
|
||||
set (BOOST_COMMON_ARGS
|
||||
${BOOST_OPENSSL_DIR}
|
||||
--prefix=${EXTERNAL_BUILD_ROOT}
|
||||
address-model=${BOOST_ADDRESS_MODEL}
|
||||
architecture=${BOOST_ARCH}
|
||||
cxxflags=-std=c++${CMAKE_CXX_STANDARD}
|
||||
cxxstd=${CMAKE_CXX_STANDARD}
|
||||
define=BOOST_ASIO_HAS_STD_STRING_VIEW
|
||||
define=BOOST_SYSTEM_NO_DEPRECATED
|
||||
link=static
|
||||
linkflags=-std=c++${CMAKE_CXX_STANDARD}
|
||||
threading=multi
|
||||
variant=${CMAKE_BUILD_TYPE_LOWER}
|
||||
-sZLIB_BINARY=zlibstatic${DEBUG_EXTRA}
|
||||
-sZLIB_LIBPATH="${EXTERNAL_BUILD_ROOT}/lib"
|
||||
-sZLIB_INCLUDE="${EXTERNAL_BUILD_ROOT}/include"
|
||||
)
|
||||
|
||||
if (MINGW)
|
||||
set(BOOST_COMMON_ARGS
|
||||
${BOOST_COMMON_ARGS}
|
||||
--user-config=./user-config.jam
|
||||
)
|
||||
set(BOOST_TARGET_OS target-os=windows)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(boost_project
|
||||
DOWNLOAD_NO_PROGRESS 1
|
||||
URL ${BOOST_DOWNLOAD_URL}
|
||||
PREFIX ${BOOST_BUILD_ROOT}
|
||||
BUILD_IN_SOURCE 1
|
||||
CONFIGURE_COMMAND
|
||||
cp -f ${CMAKE_CURRENT_SOURCE_DIR}/3rd_party/user-config.jam . &&
|
||||
./bootstrap.sh
|
||||
${BOOST_TOOLSET}
|
||||
${BOOST_TARGET_OS}
|
||||
--with-libraries=atomic,chrono,date_time,filesystem,random,regex,serialization,system,thread
|
||||
BUILD_COMMAND
|
||||
./b2
|
||||
${BOOST_COMMON_ARGS}
|
||||
${BOOST_TARGET_OS}
|
||||
INSTALL_COMMAND
|
||||
./b2
|
||||
${BOOST_COMMON_ARGS}
|
||||
${BOOST_TARGET_OS}
|
||||
install
|
||||
)
|
||||
|
||||
add_dependencies(boost_project openssl_project)
|
||||
|
||||
set(BOOST_ROOT ${BOOST_BUILD_ROOT}/src/boost_project)
|
||||
if (MINGW)
|
||||
set(BOOST_GCC_VERSION ${CMAKE_CXX_COMPILER_VERSION})
|
||||
string(REPLACE "." ";" BOOST_GCC_VERSION_LIST ${BOOST_GCC_VERSION})
|
||||
list(GET BOOST_GCC_VERSION_LIST 0 BOOST_GCC_MAJOR_VERSION)
|
||||
# set(BOOST_LIB_EXTRA "-mgw${BOOST_GCC_MAJOR_VERSION}-mt-x64-${BOOST_MAJOR_VERSION}_${BOOST_MINOR_VERSION}")
|
||||
endif()
|
||||
|
||||
set(Boost_LIBRARIES
|
||||
libboost_system${BOOST_LIB_EXTRA}.a
|
||||
libboost_atomic${BOOST_LIB_EXTRA}.a
|
||||
libboost_chrono${BOOST_LIB_EXTRA}.a
|
||||
libboost_date_time${BOOST_LIB_EXTRA}.a
|
||||
libboost_filesystem${BOOST_LIB_EXTRA}.a
|
||||
libboost_random${BOOST_LIB_EXTRA}.a
|
||||
libboost_regex${BOOST_LIB_EXTRA}.a
|
||||
libboost_serialization${BOOST_LIB_EXTRA}.a
|
||||
libboost_thread${BOOST_LIB_EXTRA}.a
|
||||
)
|
||||
|
||||
add_dependencies(boost_project zlib_project)
|
||||
|
@ -31,14 +31,20 @@ set(CURL_CMAKE_ARGS
|
||||
-DUSE_LIBIDN2=OFF
|
||||
)
|
||||
|
||||
if (MINGW AND CMAKE_TOOLCHAIN_FILE)
|
||||
if (CMAKE_TOOLCHAIN_FILE)
|
||||
set(CURL_CMAKE_ARGS
|
||||
${CURL_CMAKE_ARGS}
|
||||
-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (MINGW)
|
||||
set(CURL_CMAKE_ARGS
|
||||
${CURL_CMAKE_ARGS}
|
||||
-DCURL_USE_OPENSSL=OFF
|
||||
-DUSE_WIN32_CRYPTO=ON
|
||||
)
|
||||
elseif(NOT MINGW)
|
||||
else()
|
||||
set(CURL_CMAKE_ARGS
|
||||
${CURL_CMAKE_ARGS}
|
||||
-DCURL_USE_OPENSSL=ON
|
||||
@ -54,9 +60,8 @@ ExternalProject_Add(curl_project
|
||||
|
||||
set(REPERTORY_DEFINITIONS ${REPERTORY_DEFINITIONS} -DCURL_STATICLIB=ON -DCURL_DISABLE_LDAP=ON)
|
||||
|
||||
if (MSVC)
|
||||
set(CURL_LIBRARIES ${EXTERNAL_BUILD_ROOT}/lib/libcurl${DEBUG_EXTRA2}${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
else()
|
||||
set(CURL_LIBRARIES libcurl${DEBUG_EXTRA2}${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
add_dependencies(curl_project openssl_project)
|
||||
endif()
|
||||
set(CURL_LIBRARIES libcurl${DEBUG_EXTRA2}${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
add_dependencies(curl_project
|
||||
openssl_project
|
||||
zlib_project
|
||||
)
|
||||
|
@ -73,41 +73,6 @@ if (UNIX OR MINGW)
|
||||
${REPERTORY_COMMON_FLAG_LIST}
|
||||
-std=c++${CMAKE_CXX_STANDARD}
|
||||
)
|
||||
elseif (MSVC)
|
||||
set(REPERTORY_C_FLAGS_LIST
|
||||
${REPERTORY_C_FLAGS_LIST}
|
||||
/D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING
|
||||
/DNOMINMAX
|
||||
/bigobj
|
||||
/Zi
|
||||
)
|
||||
|
||||
set(REPERTORY_CXX_FLAGS_LIST
|
||||
${REPERTORY_CXX_FLAGS_LIST}
|
||||
/D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING
|
||||
/DNOMINMAX
|
||||
/bigobj
|
||||
/Zi
|
||||
)
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(REPERTORY_C_FLAGS_LIST
|
||||
${REPERTORY_C_FLAGS_LIST}
|
||||
/DEBUG
|
||||
)
|
||||
|
||||
set(REPERTORY_CXX_FLAGS_LIST
|
||||
${REPERTORY_CXX_FLAGS_LIST}
|
||||
/DEBUG
|
||||
)
|
||||
|
||||
set(REPERTORY_SHARED_LINKER_FLAGS_LIST
|
||||
${REPERTORY_SHARED_LINKER_FLAGS_LIST}
|
||||
/DEBUG
|
||||
/OPT:REF
|
||||
/OPT:ICF
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
list(JOIN REPERTORY_CXX_FLAGS_LIST " " REPERTORY_CXX_FLAGS_LIST)
|
||||
|
@ -1,5 +1,5 @@
|
||||
function(copy_support_files target)
|
||||
if (MSVC OR MINGW)
|
||||
if (MINGW)
|
||||
add_custom_command(
|
||||
TARGET ${target}
|
||||
POST_BUILD
|
||||
|
@ -16,17 +16,7 @@ add_dependencies(librepertory
|
||||
boost_project
|
||||
curl_project
|
||||
libsodium_project
|
||||
openssl_project
|
||||
rocksdb_project
|
||||
zlib_project
|
||||
)
|
||||
|
||||
if (LINUX)
|
||||
add_dependencies(librepertory libuuid_project)
|
||||
endif()
|
||||
|
||||
if (LINUX OR MINGW OR MACOS)
|
||||
add_dependencies(librepertory openssl_project)
|
||||
endif()
|
||||
|
||||
if (MSVC OR MINGW)
|
||||
add_dependencies(librepertory zlib_project)
|
||||
endif()
|
||||
|
@ -2,46 +2,26 @@ set(LIBSODIUM_PROJECT_NAME libsodium_${LIBSODIUM_VERSION})
|
||||
set(LIBSODIUM_BUILD_ROOT ${EXTERNAL_BUILD_ROOT}/builds/${LIBSODIUM_PROJECT_NAME})
|
||||
set(LIBSODIUM_BUILD_TYPE ${EXTERNAL_BUILD_TYPE})
|
||||
|
||||
if (MSVC)
|
||||
ExternalProject_Add(libsodium_project
|
||||
DOWNLOAD_NO_PROGRESS 1
|
||||
PREFIX ${LIBSODIUM_BUILD_ROOT}
|
||||
BUILD_IN_SOURCE 1
|
||||
URL https://github.com/jedisct1/libsodium/releases/download/${LIBSODIUM_VERSION}-RELEASE/libsodium-${LIBSODIUM_VERSION}.tar.gz
|
||||
CONFIGURE_COMMAND echo "Skipping Configure"
|
||||
BUILD_COMMAND cd builds\\msvc\\vs2019 && msbuild
|
||||
libsodium.sln
|
||||
/p:Configuration=Static${LIBSODIUM_BUILD_TYPE}
|
||||
/p:Platform=x64
|
||||
/t:libsodium
|
||||
INSTALL_COMMAND echo "Skipping Install"
|
||||
)
|
||||
link_directories(PRIVATE ${LIBSODIUM_BUILD_ROOT}/src/libsodium_project/bin/x64/${LIBSODIUM_BUILD_TYPE}/v142/static)
|
||||
set(LIBSODIUM_LIBRARIES libsodium.lib)
|
||||
add_definitions(-DSODIUM_STATIC)
|
||||
include_directories(SYSTEM
|
||||
${LIBSODIUM_BUILD_ROOT}/src/libsodium_project/src/libsodium/include
|
||||
${LIBSODIUM_BUILD_ROOT}/src/libsodium_project/builds/msvc
|
||||
)
|
||||
else()
|
||||
if (MINGW)
|
||||
set(LIBSODIUM_HOST --host=x86_64-w64-mingw32)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(libsodium_project
|
||||
DOWNLOAD_NO_PROGRESS 1
|
||||
PREFIX ${LIBSODIUM_BUILD_ROOT}
|
||||
BUILD_IN_SOURCE 1
|
||||
URL https://github.com/jedisct1/libsodium/releases/download/${LIBSODIUM_VERSION}-RELEASE/libsodium-${LIBSODIUM_VERSION}.tar.gz
|
||||
CONFIGURE_COMMAND
|
||||
./configure
|
||||
${LIBSODIUM_HOST}
|
||||
--prefix=${EXTERNAL_BUILD_ROOT}
|
||||
--enable-shared=no
|
||||
--enable-static=yes
|
||||
--disable-asm
|
||||
BUILD_COMMAND make
|
||||
INSTALL_COMMAND make install
|
||||
)
|
||||
set(LIBSODIUM_LIBRARIES libsodium.a)
|
||||
if (MINGW)
|
||||
set(LIBSODIUM_HOST --host=x86_64-w64-mingw32)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(libsodium_project
|
||||
DOWNLOAD_NO_PROGRESS 1
|
||||
PREFIX ${LIBSODIUM_BUILD_ROOT}
|
||||
BUILD_IN_SOURCE 1
|
||||
URL https://github.com/jedisct1/libsodium/releases/download/${LIBSODIUM_VERSION}-RELEASE/libsodium-${LIBSODIUM_VERSION}.tar.gz
|
||||
CONFIGURE_COMMAND
|
||||
./configure
|
||||
${LIBSODIUM_HOST}
|
||||
--prefix=${EXTERNAL_BUILD_ROOT}
|
||||
--enable-shared=no
|
||||
--enable-static=yes
|
||||
--disable-asm
|
||||
BUILD_COMMAND make
|
||||
INSTALL_COMMAND make install
|
||||
)
|
||||
|
||||
set(LIBSODIUM_LIBRARIES libsodium.a)
|
||||
|
||||
add_dependencies(libsodium_project zlib_project)
|
||||
|
@ -1,17 +0,0 @@
|
||||
if (LINUX)
|
||||
set(LIBUUID_PROJECT_NAME libuuid_${LIBUUID_VERSION})
|
||||
set(LIBUUID_BUILD_ROOT ${EXTERNAL_BUILD_ROOT}/builds/${LIBUUID_PROJECT_NAME})
|
||||
#URL "https://www.mirrorservice.org/sites/ftp.ossp.org/pkg/lib/uuid/uuid-${LIBUUID_VERSION}.tar.gz"
|
||||
ExternalProject_Add(libuuid_project
|
||||
DOWNLOAD_NO_PROGRESS 1
|
||||
PREFIX ${LIBUUID_BUILD_ROOT}
|
||||
URL https://src.fedoraproject.org/repo/pkgs/uuid/uuid-${LIBUUID_VERSION}.tar.gz/5db0d43a9022a6ebbbc25337ae28942f/uuid-${LIBUUID_VERSION}.tar.gz
|
||||
BUILD_IN_SOURCE 1
|
||||
CONFIGURE_COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/3rd_party/config.guess ./config.guess &&
|
||||
cp ${CMAKE_CURRENT_SOURCE_DIR}/3rd_party/config.sub ./config.sub &&
|
||||
CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER};./configure --disable-shared --enable-static --prefix=${EXTERNAL_BUILD_ROOT}
|
||||
BUILD_COMMAND CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER};make
|
||||
INSTALL_COMMAND make install
|
||||
)
|
||||
set(LIBUUID_LIBRARIES libuuid.a)
|
||||
endif()
|
@ -1,43 +1,36 @@
|
||||
if (MACOS OR LINUX OR MINGW)
|
||||
if (IS_CLANG_COMPILER)
|
||||
set(OPENSSL_COMPILE_TYPE_EXTRA -clang)
|
||||
endif()
|
||||
|
||||
if (MACOS)
|
||||
set(OPENSSL_COMPILE_TYPE darwin64-x86_64-cc)
|
||||
elseif(IS_ARM64)
|
||||
set(OPENSSL_COMPILE_TYPE linux-aarch64${OPENSSL_COMPILE_TYPE_EXTRA})
|
||||
elseif(MINGW)
|
||||
if (CMAKE_TOOLCHAIN_FILE)
|
||||
set(OPENSSL_COMPILE_TYPE --cross-compile-prefix=x86_64-w64-mingw32- mingw64${OPENSSL_COMPILE_TYPE_EXTRA})
|
||||
else()
|
||||
set(OPENSSL_COMPILE_TYPE mingw64${OPENSSL_COMPILE_TYPE_EXTRA})
|
||||
endif()
|
||||
else()
|
||||
set(OPENSSL_COMPILE_TYPE linux-x86_64${OPENSSL_COMPILE_TYPE_EXTRA})
|
||||
endif()
|
||||
|
||||
set(OPENSSL_PROJECT_NAME openssl_${OPENSSL_VERSION})
|
||||
set(OPENSSL_BUILD_ROOT ${EXTERNAL_BUILD_ROOT}/builds/${OPENSSL_PROJECT_NAME})
|
||||
ExternalProject_Add(openssl_project
|
||||
DOWNLOAD_NO_PROGRESS 1
|
||||
URL https://github.com/openssl/openssl/archive/refs/tags/OpenSSL_${OPENSSL_VERSION}.tar.gz
|
||||
PREFIX ${OPENSSL_BUILD_ROOT}
|
||||
BUILD_IN_SOURCE 1
|
||||
CONFIGURE_COMMAND ./Configure no-shared ${OPENSSL_COMPILE_TYPE} --openssldir=${EXTERNAL_BUILD_ROOT}/ssl --prefix=${EXTERNAL_BUILD_ROOT}
|
||||
BUILD_COMMAND make -j1
|
||||
INSTALL_COMMAND make install
|
||||
)
|
||||
|
||||
if (MACOS)
|
||||
set(OPENSSL_LIBRARIES
|
||||
${EXTERNAL_BUILD_ROOT}/lib/libssl.a
|
||||
${EXTERNAL_BUILD_ROOT}/lib/libcrypto.a
|
||||
)
|
||||
else()
|
||||
set(OPENSSL_LIBRARIES
|
||||
libssl.a
|
||||
libcrypto.a
|
||||
)
|
||||
endif()
|
||||
if (IS_CLANG_COMPILER)
|
||||
set(OPENSSL_COMPILE_TYPE_EXTRA -clang)
|
||||
endif()
|
||||
|
||||
if (MACOS)
|
||||
set(OPENSSL_COMPILE_TYPE darwin64-x86_64-cc)
|
||||
elseif(IS_ARM64)
|
||||
set(OPENSSL_COMPILE_TYPE linux-aarch64${OPENSSL_COMPILE_TYPE_EXTRA})
|
||||
elseif(MINGW)
|
||||
if (CMAKE_TOOLCHAIN_FILE)
|
||||
set(OPENSSL_COMPILE_TYPE --cross-compile-prefix=x86_64-w64-mingw32- mingw64${OPENSSL_COMPILE_TYPE_EXTRA})
|
||||
else()
|
||||
set(OPENSSL_COMPILE_TYPE mingw64${OPENSSL_COMPILE_TYPE_EXTRA})
|
||||
endif()
|
||||
else()
|
||||
set(OPENSSL_COMPILE_TYPE linux-x86_64${OPENSSL_COMPILE_TYPE_EXTRA})
|
||||
endif()
|
||||
|
||||
set(OPENSSL_PROJECT_NAME openssl_${OPENSSL_VERSION})
|
||||
set(OPENSSL_BUILD_ROOT ${EXTERNAL_BUILD_ROOT}/builds/${OPENSSL_PROJECT_NAME})
|
||||
ExternalProject_Add(openssl_project
|
||||
DOWNLOAD_NO_PROGRESS 1
|
||||
URL https://github.com/openssl/openssl/archive/refs/tags/OpenSSL_${OPENSSL_VERSION}.tar.gz
|
||||
PREFIX ${OPENSSL_BUILD_ROOT}
|
||||
BUILD_IN_SOURCE 1
|
||||
CONFIGURE_COMMAND ./Configure no-shared ${OPENSSL_COMPILE_TYPE} --openssldir=${EXTERNAL_BUILD_ROOT}/ssl --prefix=${EXTERNAL_BUILD_ROOT}
|
||||
BUILD_COMMAND make -j1
|
||||
INSTALL_COMMAND make install
|
||||
)
|
||||
|
||||
set(OPENSSL_LIBRARIES
|
||||
${EXTERNAL_BUILD_ROOT}/lib/libssl.a
|
||||
${EXTERNAL_BUILD_ROOT}/lib/libcrypto.a
|
||||
)
|
||||
|
||||
add_dependencies(openssl_project zlib_project)
|
||||
|
@ -26,57 +26,41 @@ set(ROCKSDB_CMAKE_ARGS
|
||||
-DWITH_TOOLS=OFF
|
||||
)
|
||||
|
||||
if(MSVC)
|
||||
if (MINGW)
|
||||
if (CMAKE_TOOLCHAIN_FILE)
|
||||
set(ROCKSDB_CMAKE_ARGS
|
||||
${ROCKSDB_CMAKE_ARGS}
|
||||
-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
|
||||
)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(rocksdb_project
|
||||
DOWNLOAD_NO_PROGRESS 1
|
||||
URL https://github.com/facebook/rocksdb/archive/v${ROCKSDB_VERSION}.tar.gz
|
||||
PREFIX ${ROCKSDB_BUILD_ROOT}
|
||||
CMAKE_ARGS ${ROCKSDB_CMAKE_ARGS}
|
||||
CMAKE_ARGS ${ROCKSDB_CMAKE_ARGS} -DWITH_GFLAGS=OFF
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} -E echo "Skipping install step."
|
||||
)
|
||||
|
||||
set(ROCKSDB_INCLUDE_DIRS ${ROCKSDB_BUILD_ROOT}/src/rocksdb_project/include)
|
||||
|
||||
if (CMAKE_GENERATOR_LOWER STREQUAL "nmake makefiles")
|
||||
set(ROCKSDB_LIBRARIES ${ROCKSDB_BUILD_ROOT}/src/rocksdb_project-build/rocksdb.lib)
|
||||
else ()
|
||||
set(ROCKSDB_LIBRARIES ${ROCKSDB_BUILD_ROOT}/src/rocksdb_project-build/${CMAKE_BUILD_TYPE}/rocksdb.lib)
|
||||
endif ()
|
||||
set(ROCKSDB_LIBRARIES ${ROCKSDB_BUILD_ROOT}/src/rocksdb_project-build/librocksdb.a)
|
||||
include_directories(SYSTEM ${ROCKSDB_BUILD_ROOT}/src/rocksdb_project/include)
|
||||
else()
|
||||
if (MINGW)
|
||||
if (CMAKE_TOOLCHAIN_FILE)
|
||||
set(ROCKSDB_CMAKE_ARGS
|
||||
${ROCKSDB_CMAKE_ARGS}
|
||||
-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
|
||||
)
|
||||
endif()
|
||||
ExternalProject_Add(rocksdb_project
|
||||
DOWNLOAD_NO_PROGRESS 1
|
||||
URL https://github.com/facebook/rocksdb/archive/v${ROCKSDB_VERSION}.tar.gz
|
||||
PREFIX ${ROCKSDB_BUILD_ROOT}
|
||||
CMAKE_ARGS ${ROCKSDB_CMAKE_ARGS} -DWITH_GFLAGS=OFF
|
||||
)
|
||||
|
||||
ExternalProject_Add(rocksdb_project
|
||||
DOWNLOAD_NO_PROGRESS 1
|
||||
URL https://github.com/facebook/rocksdb/archive/v${ROCKSDB_VERSION}.tar.gz
|
||||
PREFIX ${ROCKSDB_BUILD_ROOT}
|
||||
CMAKE_ARGS ${ROCKSDB_CMAKE_ARGS} -DWITH_GFLAGS=OFF
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} -E echo "Skipping install step."
|
||||
)
|
||||
|
||||
set(ROCKSDB_LIBRARIES ${ROCKSDB_BUILD_ROOT}/src/rocksdb_project-build/librocksdb.a)
|
||||
include_directories(SYSTEM ${ROCKSDB_BUILD_ROOT}/src/rocksdb_project/include)
|
||||
if (MACOS)
|
||||
set(ROCKSDB_LIBRARIES ${EXTERNAL_BUILD_ROOT}/lib/librocksdb.a)
|
||||
else()
|
||||
ExternalProject_Add(rocksdb_project
|
||||
DOWNLOAD_NO_PROGRESS 1
|
||||
URL https://github.com/facebook/rocksdb/archive/v${ROCKSDB_VERSION}.tar.gz
|
||||
PREFIX ${ROCKSDB_BUILD_ROOT}
|
||||
CMAKE_ARGS ${ROCKSDB_CMAKE_ARGS} -DWITH_GFLAGS=OFF
|
||||
)
|
||||
|
||||
if (MACOS)
|
||||
set(ROCKSDB_LIBRARIES ${EXTERNAL_BUILD_ROOT}/lib/librocksdb.a)
|
||||
else()
|
||||
set(ROCKSDB_LIBRARIES librocksdb.a)
|
||||
endif()
|
||||
set(ROCKSDB_LIBRARIES librocksdb.a)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (MSVC OR LINUX OR MINGW)
|
||||
if (LINUX OR MINGW)
|
||||
add_dependencies(rocksdb_project curl_project)
|
||||
endif()
|
||||
|
||||
add_dependencies(rocksdb_project zlib_project)
|
||||
|
@ -8,7 +8,7 @@ else()
|
||||
endif()
|
||||
|
||||
set(CMAKE_COLOR_MAKEFILE OFF)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
|
@ -4,58 +4,33 @@ if (REPERTORY_ENABLE_TESTING)
|
||||
|
||||
set(GTEST_PROJECT_NAME gtest_${GTEST_VERSION})
|
||||
set(GTEST_BUILD_ROOT ${EXTERNAL_BUILD_ROOT}/builds/${GTEST_PROJECT_NAME})
|
||||
if (MSVC)
|
||||
ExternalProject_Add(gtest_project
|
||||
DOWNLOAD_NO_PROGRESS 1
|
||||
URL https://github.com/google/googletest/archive/refs/tags/${GTEST_VERSION}.tar.gz
|
||||
PREFIX ${GTEST_BUILD_ROOT}
|
||||
CMAKE_ARGS
|
||||
-DCMAKE_POSITION_INDEPENDENT_CODE=${CMAKE_POSITION_INDEPENDENT_CODE}
|
||||
-DCMAKE_BUILD_TYPE=${EXTERNAL_BUILD_TYPE}
|
||||
-Dgtest_force_shared_crt=OFF
|
||||
-DBUILD_SHARED_LIBS=ON
|
||||
-DCMAKE_CXX_FLAGS=/D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} -E echo "Skipping install step."
|
||||
)
|
||||
if (MACOS)
|
||||
set(GTEST_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
|
||||
set(GTEST_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
|
||||
else()
|
||||
if (MACOS)
|
||||
set(GTEST_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
|
||||
set(GTEST_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
|
||||
else()
|
||||
set(GTEST_C_FLAGS ${CMAKE_C_FLAGS})
|
||||
set(GTEST_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
endif()
|
||||
ExternalProject_Add(gtest_project
|
||||
DOWNLOAD_NO_PROGRESS 1
|
||||
URL https://github.com/google/googletest/archive/refs/tags/${GTEST_VERSION}.tar.gz
|
||||
PREFIX ${GTEST_BUILD_ROOT}
|
||||
CMAKE_ARGS
|
||||
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
|
||||
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
|
||||
-DCMAKE_C_FLAGS=${GTEST_C_FLAGS}
|
||||
-DCMAKE_CXX_FLAGS=${GTEST_CXX_FLAGS}
|
||||
-DCMAKE_POSITION_INDEPENDENT_CODE=${CMAKE_POSITION_INDEPENDENT_CODE}
|
||||
-DCMAKE_BUILD_TYPE=${EXTERNAL_BUILD_TYPE}
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} -E echo "Skipping install step."
|
||||
)
|
||||
set(GTEST_C_FLAGS ${CMAKE_C_FLAGS})
|
||||
set(GTEST_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
endif()
|
||||
ExternalProject_Add(gtest_project
|
||||
DOWNLOAD_NO_PROGRESS 1
|
||||
URL https://github.com/google/googletest/archive/refs/tags/${GTEST_VERSION}.tar.gz
|
||||
PREFIX ${GTEST_BUILD_ROOT}
|
||||
CMAKE_ARGS
|
||||
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
|
||||
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
|
||||
-DCMAKE_C_FLAGS=${GTEST_C_FLAGS}
|
||||
-DCMAKE_CXX_FLAGS=${GTEST_CXX_FLAGS}
|
||||
-DCMAKE_POSITION_INDEPENDENT_CODE=${CMAKE_POSITION_INDEPENDENT_CODE}
|
||||
-DCMAKE_BUILD_TYPE=${EXTERNAL_BUILD_TYPE}
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} -E echo "Skipping install step."
|
||||
)
|
||||
|
||||
set(GTEST_INCLUDE_DIRS
|
||||
${GTEST_BUILD_ROOT}/src/gtest_project/googletest/include
|
||||
${GTEST_BUILD_ROOT}/src/gtest_project/googlemock/include
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
if (NOT CMAKE_GENERATOR_LOWER STREQUAL "nmake makefiles")
|
||||
set (GTEST_PATH_EXTRA ${CMAKE_BUILD_TYPE}/)
|
||||
endif()
|
||||
set(GTEST_LIBRARIES
|
||||
${GTEST_BUILD_ROOT}/src/gtest_project-build/lib/${GTEST_PATH_EXTRA}gmock${DEBUG_EXTRA}.lib
|
||||
${GTEST_BUILD_ROOT}/src/gtest_project-build/lib/${GTEST_PATH_EXTRA}gmock_main${DEBUG_EXTRA}.lib
|
||||
${GTEST_BUILD_ROOT}/src/gtest_project-build/lib/${GTEST_PATH_EXTRA}gtest${DEBUG_EXTRA}.lib
|
||||
${GTEST_BUILD_ROOT}/src/gtest_project-build/lib/${GTEST_PATH_EXTRA}gtest_main${DEBUG_EXTRA}.lib
|
||||
)
|
||||
elseif (UNIX OR MINGW)
|
||||
if(UNIX OR MINGW)
|
||||
set(GTEST_LIBRARIES
|
||||
${GTEST_BUILD_ROOT}/src/gtest_project-build/lib/libgmock.a
|
||||
${GTEST_BUILD_ROOT}/src/gtest_project-build/lib/libgtest.a
|
||||
@ -72,7 +47,11 @@ if (REPERTORY_ENABLE_TESTING)
|
||||
)
|
||||
|
||||
add_project_executable(unittests "${UNITTEST_SOURCES}")
|
||||
add_dependencies(unittests gtest_project)
|
||||
add_dependencies(unittests
|
||||
gtest_project
|
||||
zlib_project
|
||||
)
|
||||
|
||||
target_compile_definitions(unittests PUBLIC
|
||||
GTEST_LINKED_AS_SHARED_LIBRARY=1
|
||||
REPERTORY_TESTING
|
||||
@ -83,28 +62,5 @@ if (REPERTORY_ENABLE_TESTING)
|
||||
)
|
||||
target_link_libraries(unittests PRIVATE ${GTEST_LIBRARIES})
|
||||
|
||||
if (MSVC)
|
||||
add_custom_command(TARGET unittests
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${GTEST_BUILD_ROOT}/src/gtest_project-build/bin/${GTEST_PATH_EXTRA}gmock${DEBUG_EXTRA}.dll ${CMAKE_CURRENT_BINARY_DIR}/${GTEST_PATH_EXTRA}
|
||||
)
|
||||
add_custom_command(TARGET unittests
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${GTEST_BUILD_ROOT}/src/gtest_project-build/bin/${GTEST_PATH_EXTRA}gmock_main${DEBUG_EXTRA}.dll ${CMAKE_CURRENT_BINARY_DIR}/${GTEST_PATH_EXTRA}
|
||||
)
|
||||
add_custom_command(TARGET unittests
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${GTEST_BUILD_ROOT}/src/gtest_project-build/bin/${GTEST_PATH_EXTRA}gtest${DEBUG_EXTRA}.dll ${CMAKE_CURRENT_BINARY_DIR}/${GTEST_PATH_EXTRA}
|
||||
)
|
||||
add_custom_command(TARGET unittests
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${GTEST_BUILD_ROOT}/src/gtest_project-build/bin/${GTEST_PATH_EXTRA}gtest_main${DEBUG_EXTRA}.dll ${CMAKE_CURRENT_BINARY_DIR}/${GTEST_PATH_EXTRA}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (CMAKE_GENERATOR_LOWER STREQUAL "nmake makefiles")
|
||||
add_test(NAME AllTests COMMAND unittests WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
else()
|
||||
add_test(NAME AllTests COMMAND unittests WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE})
|
||||
endif()
|
||||
add_test(NAME AllTests COMMAND unittests WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE})
|
||||
endif()
|
||||
|
@ -1,16 +1,11 @@
|
||||
set(BOOST_MAJOR_VERSION 1)
|
||||
set(BOOST_MINOR_VERSION 78)
|
||||
set(BOOST_MSVC_TOOLSET msvc-14.2)
|
||||
set(BOOST_MSVC_TOOLSET_DLL 142)
|
||||
set(BOOST_MINOR_VERSION 83)
|
||||
set(BOOST_REVISION 0)
|
||||
set(BOOST_VERSION ${BOOST_MAJOR_VERSION}.${BOOST_MINOR_VERSION}.${BOOST_REVISION})
|
||||
set(BOOST_VERSION_DL ${BOOST_MAJOR_VERSION}_${BOOST_MINOR_VERSION}_${BOOST_REVISION})
|
||||
set(BOOST_VERSION_DLL ${BOOST_MAJOR_VERSION}_${BOOST_MINOR_VERSION})
|
||||
set(CURL_VERSION 8_3_0)
|
||||
set(CURL_VERSION 8_4_0)
|
||||
set(GTEST_VERSION v1.14.0)
|
||||
set(LIBSODIUM_VERSION 1.0.18)
|
||||
set(LIBSODIUM_VERSION 1.0.19)
|
||||
set(LIBUUID_VERSION 1.6.2)
|
||||
set(OPENSSL_VERSION 1_1_1w)
|
||||
set(ROCKSDB_VERSION 8.5.3)
|
||||
set(ROCKSDB_VERSION 8.6.7)
|
||||
set(WINFSP_VERSION 2.0)
|
||||
set(ZLIB_VERSION v1.3)
|
||||
|
@ -1,42 +1,31 @@
|
||||
if (MSVC OR MINGW)
|
||||
set(ZLIB_PROJECT_NAME zlib_${ZLIB_VERSION})
|
||||
set(ZLIB_BUILD_ROOT ${EXTERNAL_BUILD_ROOT}/builds/${ZLIB_PROJECT_NAME})
|
||||
set(ZLIB_PROJECT_NAME zlib_${ZLIB_VERSION})
|
||||
set(ZLIB_BUILD_ROOT ${EXTERNAL_BUILD_ROOT}/builds/${ZLIB_PROJECT_NAME})
|
||||
set(ZLIB_CMAKE_ARGS
|
||||
-DCMAKE_BUILD_TYPE=${EXTERNAL_BUILD_TYPE}
|
||||
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
|
||||
-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}
|
||||
-DCMAKE_GENERATOR=${CMAKE_GENERATOR}
|
||||
-DCMAKE_INSTALL_PREFIX=${EXTERNAL_BUILD_ROOT}
|
||||
-DCMAKE_POSITION_INDEPENDENT_CODE=${CMAKE_POSITION_INDEPENDENT_CODE}
|
||||
-DCMAKE_SHARED_LINKER_FLAGS=${CMAKE_SHARED_LINKER_FLAGS}
|
||||
)
|
||||
|
||||
if (CMAKE_TOOLCHAIN_FILE)
|
||||
set(ZLIB_CMAKE_ARGS
|
||||
-DCMAKE_BUILD_TYPE=${EXTERNAL_BUILD_TYPE}
|
||||
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
|
||||
-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}
|
||||
-DCMAKE_GENERATOR=${CMAKE_GENERATOR}
|
||||
-DCMAKE_INSTALL_PREFIX=${EXTERNAL_BUILD_ROOT}
|
||||
-DCMAKE_POSITION_INDEPENDENT_CODE=${CMAKE_POSITION_INDEPENDENT_CODE}
|
||||
-DCMAKE_SHARED_LINKER_FLAGS=${CMAKE_SHARED_LINKER_FLAGS}
|
||||
${ZLIB_CMAKE_ARGS}
|
||||
-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
|
||||
)
|
||||
|
||||
if (MINGW AND CMAKE_TOOLCHAIN_FILE)
|
||||
set(ZLIB_CMAKE_ARGS
|
||||
${ZLIB_CMAKE_ARGS}
|
||||
-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
|
||||
)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(zlib_project
|
||||
DOWNLOAD_NO_PROGRESS 1
|
||||
URL https://github.com/madler/zlib/archive/${ZLIB_VERSION}.tar.gz
|
||||
PREFIX ${ZLIB_BUILD_ROOT}
|
||||
CMAKE_ARGS ${ZLIB_CMAKE_ARGS}
|
||||
)
|
||||
|
||||
if (MINGW)
|
||||
set(ZLIB_LIBRARIES ${EXTERNAL_BUILD_ROOT}/lib/libzlibstatic${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
else()
|
||||
set(ZLIB_LIBRARIES ${EXTERNAL_BUILD_ROOT}/lib/zlibstatic${DEBUG_EXTRA}${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
endif()
|
||||
elseif(LINUX)
|
||||
find_library(ZLIB_LIBRARIES NO_CACHE NAMES z)
|
||||
if (NOT ZLIB_LIBRARIES)
|
||||
message(FATAL_ERROR "'zlib' not found")
|
||||
endif()
|
||||
|
||||
if (REPERTORY_MUSL)
|
||||
set(ZLIB_LIBRARIES libz.a)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(zlib_project
|
||||
DOWNLOAD_NO_PROGRESS 1
|
||||
URL https://github.com/madler/zlib/archive/${ZLIB_VERSION}.tar.gz
|
||||
PREFIX ${ZLIB_BUILD_ROOT}
|
||||
CMAKE_ARGS ${ZLIB_CMAKE_ARGS}
|
||||
)
|
||||
|
||||
if(MINGW)
|
||||
set(ZLIB_LIBRARIES ${EXTERNAL_BUILD_ROOT}/lib/libzlibstatic${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
else()
|
||||
set(ZLIB_LIBRARIES ${EXTERNAL_BUILD_ROOT}/lib/libz${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
endif()
|
||||
|
@ -30,39 +30,39 @@
|
||||
namespace repertory {
|
||||
class app_config final {
|
||||
public:
|
||||
[[nodiscard]] static auto default_agent_name(const provider_type &pt)
|
||||
[[nodiscard]] static auto default_agent_name(const provider_type &prov)
|
||||
-> std::string;
|
||||
|
||||
[[nodiscard]] static auto default_api_port(const provider_type &pt)
|
||||
[[nodiscard]] static auto default_api_port(const provider_type &prov)
|
||||
-> std::uint16_t;
|
||||
|
||||
[[nodiscard]] static auto default_data_directory(const provider_type &pt)
|
||||
[[nodiscard]] static auto default_data_directory(const provider_type &prov)
|
||||
-> std::string;
|
||||
|
||||
[[nodiscard]] static auto default_rpc_port(const provider_type &pt)
|
||||
[[nodiscard]] static auto default_rpc_port(const provider_type &prov)
|
||||
-> std::uint16_t;
|
||||
|
||||
[[nodiscard]] static auto get_provider_api_password(const provider_type &pt)
|
||||
[[nodiscard]] static auto get_provider_api_password(const provider_type &prov)
|
||||
-> std::string;
|
||||
|
||||
[[nodiscard]] static auto get_provider_display_name(const provider_type &pt)
|
||||
[[nodiscard]] static auto get_provider_display_name(const provider_type &prov)
|
||||
-> std::string;
|
||||
|
||||
[[nodiscard]] static auto get_provider_name(const provider_type &pt)
|
||||
[[nodiscard]] static auto get_provider_name(const provider_type &prov)
|
||||
-> std::string;
|
||||
|
||||
public:
|
||||
app_config(const provider_type &pt, const std::string &data_directory = "");
|
||||
app_config(const provider_type &prov, const std::string &data_directory = "");
|
||||
|
||||
~app_config() { save(); }
|
||||
|
||||
private:
|
||||
const provider_type pt_;
|
||||
provider_type prov_;
|
||||
std::string api_auth_;
|
||||
std::uint16_t api_port_;
|
||||
std::string api_user_;
|
||||
bool config_changed_;
|
||||
const std::string data_directory_;
|
||||
std::string data_directory_;
|
||||
std::uint8_t download_timeout_secs_;
|
||||
bool enable_chunk_downloader_timeout_;
|
||||
bool enable_comm_duration_events_;
|
||||
@ -129,7 +129,7 @@ private:
|
||||
template <typename dest, typename source>
|
||||
auto set_value(dest &dst, const source &src) -> bool {
|
||||
auto ret = false;
|
||||
recur_mutex_lock l(read_write_mutex_);
|
||||
recur_mutex_lock lock(read_write_mutex_);
|
||||
if (dst != src) {
|
||||
dst = src;
|
||||
config_changed_ = true;
|
||||
@ -244,7 +244,9 @@ public:
|
||||
download_type::fallback);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_provider_type() const -> provider_type { return pt_; }
|
||||
[[nodiscard]] auto get_provider_type() const -> provider_type {
|
||||
return prov_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_read_ahead_count() const -> std::uint8_t {
|
||||
return std::max(static_cast<std::uint8_t>(1U), read_ahead_count_);
|
||||
|
@ -23,14 +23,12 @@
|
||||
#define INCLUDE_CLI_ACTIONS_HPP_
|
||||
|
||||
#include "cli/check_version.hpp"
|
||||
#include "cli/create_directory.hpp"
|
||||
#include "cli/display_config.hpp"
|
||||
#include "cli/drive_information.hpp"
|
||||
#include "cli/get.hpp"
|
||||
#include "cli/get_directory_items.hpp"
|
||||
#include "cli/get_pinned_files.hpp"
|
||||
#include "cli/help.hpp"
|
||||
#include "cli/list_objects.hpp"
|
||||
#include "cli/mount.hpp"
|
||||
#include "cli/open_files.hpp"
|
||||
#include "cli/pin_file.hpp"
|
||||
@ -57,11 +55,6 @@ static const std::unordered_map<utils::cli::option, action, option_hasher>
|
||||
option_actions = {
|
||||
{utils::cli::options::check_version_option,
|
||||
cli::actions::check_version},
|
||||
#if defined(REPERTORY_ENABLE_S3)
|
||||
{utils::cli::options::create_directory_option,
|
||||
cli::actions::create_directory},
|
||||
{utils::cli::options::list_objects_option, cli::actions::list_objects},
|
||||
#endif
|
||||
{utils::cli::options::display_config_option,
|
||||
cli::actions::display_config},
|
||||
{utils::cli::options::drive_information_option,
|
||||
|
@ -1,80 +0,0 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef INCLUDE_CLI_CREATE_DIRECTORY_HPP_
|
||||
#define INCLUDE_CLI_CREATE_DIRECTORY_HPP_
|
||||
#if defined(REPERTORY_ENABLE_S3)
|
||||
|
||||
#include "app_config.hpp"
|
||||
#include "comm/s3/s3_comm.hpp"
|
||||
#include "platform/platform.hpp"
|
||||
#include "providers/i_provider.hpp"
|
||||
#include "providers/provider.hpp"
|
||||
#include "rpc/client/client.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/cli_utils.hpp"
|
||||
|
||||
namespace repertory::cli::actions {
|
||||
[[nodiscard]] inline auto
|
||||
create_directory(int argc, char *argv[], const std::string &data_directory,
|
||||
const provider_type &pt, const std::string &unique_id,
|
||||
std::string /* user */, std::string /* password */)
|
||||
-> exit_code {
|
||||
auto ret = exit_code::invalid_provider_type;
|
||||
|
||||
if (pt == provider_type::s3) {
|
||||
std::string api_path;
|
||||
if ((ret = utils::cli::parse_string_option(
|
||||
argc, argv, utils::cli::options::create_directory_option,
|
||||
api_path)) == exit_code::success) {
|
||||
lock_data lock(pt, unique_id);
|
||||
const auto res = lock.grab_lock(1u);
|
||||
/* if (res == lock_result::locked) { */
|
||||
/* auto port = app_config::default_api_port(pt); */
|
||||
/* utils::cli::get_api_authentication_data(user, password, port, pt,
|
||||
* data_directory); */
|
||||
/* const auto response = */
|
||||
/* client({"localhost", password, port,
|
||||
* user}).create_directory(api_path); */
|
||||
/* std::cout << static_cast<int>(response.response_type) << std::endl; */
|
||||
/* std::cout << response.data.dump(2) << std::endl; */
|
||||
/* } else */
|
||||
if (res == lock_result::success) {
|
||||
std::cout << "creating directory: '" << api_path << "'" << std::endl;
|
||||
app_config config(pt, data_directory);
|
||||
s3_comm comm(config);
|
||||
const auto res = comm.create_directory(api_path);
|
||||
std::cout << api_error_to_string(res) << std::endl;
|
||||
ret = exit_code::success;
|
||||
} else {
|
||||
std::cout << "failed to grab lock: '" << static_cast<int>(res) << "'"
|
||||
<< std::endl;
|
||||
ret = exit_code::lock_failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
} // namespace repertory::cli::actions
|
||||
|
||||
#endif // REPERTORY_ENABLE_S3
|
||||
#endif // INCLUDE_CLI_CREATE_DIRECTORY_HPP_
|
@ -42,11 +42,6 @@ template <typename drive> inline void help(int argc, char *argv[]) {
|
||||
std::cout << " -na,--name Unique name for S3 "
|
||||
"instance [Required]"
|
||||
<< std::endl;
|
||||
std::cout
|
||||
<< " -cd,--create_directory [API path] Create directory object in S3"
|
||||
<< std::endl;
|
||||
std::cout << " -lo,--list_objects List all S3 objects"
|
||||
<< std::endl;
|
||||
#endif // defined(REPERTORY_ENABLE_S3)
|
||||
std::cout
|
||||
<< " -gc,--generate_config Generate initial configuration"
|
||||
|
@ -1,81 +0,0 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef INCLUDE_CLI_LIST_OBJECTS_HPP_
|
||||
#define INCLUDE_CLI_LIST_OBJECTS_HPP_
|
||||
#if defined(REPERTORY_ENABLE_S3)
|
||||
|
||||
#include "app_config.hpp"
|
||||
#include "comm/s3/s3_comm.hpp"
|
||||
#include "platform/platform.hpp"
|
||||
#include "providers/i_provider.hpp"
|
||||
#include "providers/provider.hpp"
|
||||
#include "rpc/client/client.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/cli_utils.hpp"
|
||||
|
||||
namespace repertory::cli::actions {
|
||||
[[nodiscard]] inline auto
|
||||
list_objects(int /* argc */, char * /* argv */[],
|
||||
const std::string &data_directory, const provider_type &pt,
|
||||
const std::string &unique_id, std::string /* user */,
|
||||
std::string /* password */) -> exit_code {
|
||||
auto ret = exit_code::invalid_provider_type;
|
||||
|
||||
if (pt == provider_type::s3) {
|
||||
lock_data lock(pt, unique_id);
|
||||
const auto res = lock.grab_lock(1u);
|
||||
/* if (res == lock_result::locked) { */
|
||||
/* auto port = app_config::default_api_port(pt); */
|
||||
/* utils::cli::get_api_authentication_data(user, password, port, pt,
|
||||
* data_directory); */
|
||||
/* const auto response = */
|
||||
/* client({"localhost", password, port,
|
||||
* user}).create_directory(api_path); */
|
||||
/* std::cout << static_cast<int>(response.response_type) << std::endl; */
|
||||
/* std::cout << response.data.dump(2) << std::endl; */
|
||||
/* } else */
|
||||
if (res == lock_result::success) {
|
||||
app_config config(pt, data_directory);
|
||||
s3_comm comm(config);
|
||||
std::vector<directory_item> list{};
|
||||
const auto res = comm.get_object_list(list);
|
||||
if (res == api_error::success) {
|
||||
for (const auto &di : list) {
|
||||
std::cout << di.to_json().dump(2) << std::endl;
|
||||
}
|
||||
ret = exit_code::success;
|
||||
} else {
|
||||
std::cout << api_error_to_string(res) << std::endl;
|
||||
}
|
||||
} else {
|
||||
std::cout << "failed to grab lock: '" << static_cast<int>(res) << "'"
|
||||
<< std::endl;
|
||||
ret = exit_code::lock_failed;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
} // namespace repertory::cli::actions
|
||||
|
||||
#endif // REPERTORY_ENABLE_S3
|
||||
#endif // INCLUDE_CLI_LIST_OBJECTS_HPP_
|
@ -32,9 +32,9 @@ class curl_comm final : public i_http_comm {
|
||||
public:
|
||||
curl_comm() = delete;
|
||||
|
||||
explicit curl_comm(host_config hc);
|
||||
explicit curl_comm(host_config cfg);
|
||||
|
||||
explicit curl_comm(s3_config s3);
|
||||
explicit curl_comm(s3_config cfg);
|
||||
|
||||
private:
|
||||
using write_callback = size_t (*)(char *, size_t, size_t, void *);
|
||||
@ -57,9 +57,10 @@ private:
|
||||
public:
|
||||
[[nodiscard]] static auto construct_url(CURL *curl,
|
||||
const std::string &relative_path,
|
||||
const host_config &hc) -> std::string;
|
||||
const host_config &cfg)
|
||||
-> std::string;
|
||||
|
||||
[[nodiscard]] static auto create_host_config(const s3_config &config,
|
||||
[[nodiscard]] static auto create_host_config(const s3_config &cfg,
|
||||
bool use_s3_path_style)
|
||||
-> host_config;
|
||||
|
||||
@ -68,7 +69,7 @@ public:
|
||||
|
||||
template <typename request_type>
|
||||
[[nodiscard]] static auto
|
||||
make_encrypted_request(const host_config &hc, const request_type &request,
|
||||
make_encrypted_request(const host_config &cfg, const request_type &request,
|
||||
long &response_code, stop_type &stop_requested)
|
||||
-> bool {
|
||||
response_code = 0;
|
||||
@ -102,7 +103,7 @@ public:
|
||||
};
|
||||
encrypted_request.total_size = std::nullopt;
|
||||
|
||||
if (not make_request(hc, encrypted_request, response_code,
|
||||
if (not make_request(cfg, encrypted_request, response_code,
|
||||
stop_requested)) {
|
||||
return api_error::comm_error;
|
||||
}
|
||||
@ -127,11 +128,12 @@ public:
|
||||
|
||||
template <typename request_type>
|
||||
[[nodiscard]] static auto
|
||||
make_request(const host_config &hc, const request_type &request,
|
||||
make_request(const host_config &cfg, const request_type &request,
|
||||
long &response_code, stop_type &stop_requested) -> bool {
|
||||
if (request.decryption_token.has_value() &&
|
||||
not request.decryption_token.value().empty()) {
|
||||
return make_encrypted_request(hc, request, response_code, stop_requested);
|
||||
return make_encrypted_request(cfg, request, response_code,
|
||||
stop_requested);
|
||||
}
|
||||
|
||||
response_code = 0;
|
||||
@ -141,12 +143,12 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (not hc.agent_string.empty()) {
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, hc.agent_string.c_str());
|
||||
if (not cfg.agent_string.empty()) {
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, cfg.agent_string.c_str());
|
||||
}
|
||||
|
||||
if (request.allow_timeout && hc.timeout_ms) {
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, hc.timeout_ms);
|
||||
if (request.allow_timeout && cfg.timeout_ms) {
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, cfg.timeout_ms);
|
||||
}
|
||||
|
||||
std::string range_list{};
|
||||
@ -169,16 +171,16 @@ public:
|
||||
}
|
||||
|
||||
std::string parameters{};
|
||||
for (const auto &kv : request.query) {
|
||||
parameters += (parameters.empty() ? '?' : '&') + kv.first + '=' +
|
||||
url_encode(curl, kv.second, false);
|
||||
for (const auto ¶m : request.query) {
|
||||
parameters += (parameters.empty() ? '?' : '&') + param.first + '=' +
|
||||
url_encode(curl, param.second, false);
|
||||
}
|
||||
|
||||
if (not hc.api_password.empty()) {
|
||||
curl_easy_setopt(curl, CURLOPT_USERNAME, hc.api_user.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_PASSWORD, hc.api_password.c_str());
|
||||
} else if (not hc.api_user.empty()) {
|
||||
curl_easy_setopt(curl, CURLOPT_USERNAME, hc.api_user.c_str());
|
||||
if (not cfg.api_password.empty()) {
|
||||
curl_easy_setopt(curl, CURLOPT_USERNAME, cfg.api_user.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_PASSWORD, cfg.api_password.c_str());
|
||||
} else if (not cfg.api_user.empty()) {
|
||||
curl_easy_setopt(curl, CURLOPT_USERNAME, cfg.api_user.c_str());
|
||||
}
|
||||
|
||||
if (request.aws_service.has_value()) {
|
||||
@ -186,7 +188,7 @@ public:
|
||||
request.aws_service.value().c_str());
|
||||
}
|
||||
|
||||
auto url = construct_url(curl, request.get_path(), hc) + parameters;
|
||||
auto url = construct_url(curl, request.get_path(), cfg) + parameters;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
|
||||
multi_request curl_request(curl, stop_requested);
|
||||
@ -194,6 +196,7 @@ public:
|
||||
CURLcode curl_code{};
|
||||
curl_request.get_result(curl_code, response_code);
|
||||
if (curl_code != CURLE_OK) {
|
||||
std::cout << curl_easy_strerror(curl_code) << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,11 @@
|
||||
|
||||
namespace repertory::curl::requests {
|
||||
struct http_get final : http_request_base {
|
||||
http_get() = default;
|
||||
http_get(const http_get &) = default;
|
||||
http_get(http_get &&) = default;
|
||||
auto operator=(const http_get &) -> http_get & = default;
|
||||
auto operator=(http_get &&) -> http_get & = default;
|
||||
~http_get() override = default;
|
||||
|
||||
[[nodiscard]] auto set_method(CURL *curl,
|
||||
|
@ -27,14 +27,17 @@
|
||||
|
||||
namespace repertory::curl::requests {
|
||||
struct http_put_file final : http_request_base {
|
||||
http_put_file() = default;
|
||||
http_put_file(const http_put_file &) = default;
|
||||
http_put_file(http_put_file &&) = default;
|
||||
|
||||
auto operator=(const http_put_file &) -> http_put_file & = default;
|
||||
auto operator=(http_put_file &&) -> http_put_file & = default;
|
||||
|
||||
~http_put_file() override = default;
|
||||
|
||||
std::optional<std::string> encryption_token{};
|
||||
std::string file_name{};
|
||||
mutable std::shared_ptr<utils::encryption::encrypting_reader> reader{};
|
||||
std::string source_path{};
|
||||
|
||||
[[nodiscard]] auto get_path() const -> std::string override;
|
||||
std::shared_ptr<utils::encryption::encrypting_reader> reader;
|
||||
std::string source_path;
|
||||
|
||||
[[nodiscard]] auto set_method(CURL *curl, stop_type &stop_requested) const
|
||||
-> bool override;
|
||||
|
@ -39,17 +39,25 @@ struct read_file_info final {
|
||||
|
||||
inline const auto read_file_data = static_cast<read_callback>(
|
||||
[](char *buffer, size_t size, size_t nitems, void *instream) -> size_t {
|
||||
auto *rd = reinterpret_cast<read_file_info *>(instream);
|
||||
auto *read_info = reinterpret_cast<read_file_info *>(instream);
|
||||
std::size_t bytes_read{};
|
||||
auto ret =
|
||||
rd->nf->read_bytes(buffer, size * nitems, rd->offset, bytes_read);
|
||||
auto ret = read_info->nf->read_bytes(buffer, size * nitems,
|
||||
read_info->offset, bytes_read);
|
||||
if (ret) {
|
||||
rd->offset += bytes_read;
|
||||
read_info->offset += bytes_read;
|
||||
}
|
||||
return ret && not rd->stop_requested ? bytes_read : CURL_READFUNC_ABORT;
|
||||
return ret && not read_info->stop_requested ? bytes_read
|
||||
: CURL_READFUNC_ABORT;
|
||||
});
|
||||
|
||||
struct http_request_base {
|
||||
http_request_base() = default;
|
||||
http_request_base(const http_request_base &) = default;
|
||||
http_request_base(http_request_base &&) = default;
|
||||
|
||||
auto operator=(const http_request_base &) -> http_request_base & = default;
|
||||
auto operator=(http_request_base &&) -> http_request_base & = default;
|
||||
|
||||
virtual ~http_request_base() = default;
|
||||
|
||||
bool allow_timeout{};
|
||||
|
@ -1,109 +0,0 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef INCLUDE_COMM_I_S3_COMM_HPP_
|
||||
#define INCLUDE_COMM_I_S3_COMM_HPP_
|
||||
#if defined(REPERTORY_ENABLE_S3)
|
||||
|
||||
#include "types/repertory.hpp"
|
||||
#include "types/s3.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class i_provider;
|
||||
|
||||
class i_s3_comm {
|
||||
INTERFACE_SETUP(i_s3_comm);
|
||||
|
||||
public:
|
||||
[[nodiscard]] virtual auto create_directory(const std::string &api_path)
|
||||
-> api_error = 0;
|
||||
|
||||
[[nodiscard]] virtual auto directory_exists(const std::string &api_path) const
|
||||
-> api_error = 0;
|
||||
|
||||
[[nodiscard]] virtual auto file_exists(const std::string &api_path,
|
||||
const get_key_callback &get_key) const
|
||||
-> api_error = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
get_directory_item_count(const std::string &api_path,
|
||||
meta_provider_callback meta_provider) const
|
||||
-> std::size_t = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
get_directory_items(const std::string &api_path,
|
||||
meta_provider_callback meta_provider,
|
||||
directory_item_list &list) const -> api_error = 0;
|
||||
|
||||
[[nodiscard]] virtual auto get_directory_list(api_file_list &list) const
|
||||
-> api_error = 0;
|
||||
|
||||
[[nodiscard]] virtual auto get_file(const std::string &api_path,
|
||||
const get_key_callback &get_key,
|
||||
const get_name_callback &get_name,
|
||||
const get_token_callback &get_token,
|
||||
api_file &file) const -> api_error = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
get_file_list(const get_api_file_token_callback &get_api_file_token,
|
||||
const get_name_callback &get_name, api_file_list &list) const
|
||||
-> api_error = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
get_object_list(std::vector<directory_item> &list) const -> api_error = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
get_object_name(const std::string &api_path,
|
||||
const get_key_callback &get_key) const -> std::string = 0;
|
||||
|
||||
[[nodiscard]] virtual auto get_s3_config() -> s3_config = 0;
|
||||
|
||||
[[nodiscard]] virtual auto get_s3_config() const -> s3_config = 0;
|
||||
|
||||
[[nodiscard]] virtual auto is_online() const -> bool = 0;
|
||||
|
||||
[[nodiscard]] virtual auto read_file_bytes(
|
||||
const std::string &api_path, std::size_t size, std::uint64_t offset,
|
||||
data_buffer &data, const get_key_callback &get_key,
|
||||
const get_size_callback &get_size, const get_token_callback &get_token,
|
||||
stop_type &stop_requested) const -> api_error = 0;
|
||||
|
||||
[[nodiscard]] virtual auto remove_directory(const std::string &api_path)
|
||||
-> api_error = 0;
|
||||
|
||||
[[nodiscard]] virtual auto remove_file(const std::string &api_path,
|
||||
const get_key_callback &get_key)
|
||||
-> api_error = 0;
|
||||
|
||||
[[nodiscard]] virtual auto rename_file(const std::string &api_path,
|
||||
const std::string &new_api_path)
|
||||
-> api_error = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
upload_file(const std::string &api_path, const std::string &source_path,
|
||||
const std::string &encryption_token,
|
||||
const get_key_callback &get_key, const set_key_callback &set_key,
|
||||
stop_type &stop_requested) -> api_error = 0;
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // REPERTORY_ENABLE_S3
|
||||
#endif // INCLUDE_COMM_I_S3_COMM_HPP_
|
@ -56,11 +56,17 @@ private:
|
||||
|
||||
~pool() { shutdown(); }
|
||||
|
||||
public:
|
||||
pool(const pool &) = delete;
|
||||
pool(pool &&) = delete;
|
||||
auto operator=(const pool &) -> pool & = delete;
|
||||
auto operator=(pool &&) -> pool & = delete;
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<work_queue>> pool_queues_;
|
||||
std::vector<std::thread> pool_threads_;
|
||||
bool shutdown_ = false;
|
||||
std::atomic<std::uint8_t> thread_index_;
|
||||
bool shutdown_{false};
|
||||
std::atomic<std::uint8_t> thread_index_{};
|
||||
|
||||
public:
|
||||
void execute(std::uint64_t thread_id, const worker_callback &worker,
|
||||
@ -70,17 +76,26 @@ private:
|
||||
};
|
||||
|
||||
public:
|
||||
explicit client_pool(std::uint8_t pool_size = 10u)
|
||||
: pool_size_(pool_size ? pool_size : 10u) {}
|
||||
explicit client_pool(std::uint8_t pool_size = min_pool_size)
|
||||
: pool_size_(pool_size == 0U ? min_pool_size : pool_size) {}
|
||||
|
||||
~client_pool() { shutdown(); }
|
||||
|
||||
public:
|
||||
client_pool(const client_pool &) = delete;
|
||||
client_pool(client_pool &&) = delete;
|
||||
auto operator=(const client_pool &) -> client_pool & = delete;
|
||||
auto operator=(client_pool &&) -> client_pool & = delete;
|
||||
|
||||
private:
|
||||
const std::uint8_t pool_size_;
|
||||
std::uint8_t pool_size_;
|
||||
std::unordered_map<std::string, std::shared_ptr<pool>> pool_lookup_;
|
||||
std::mutex pool_mutex_;
|
||||
bool shutdown_ = false;
|
||||
|
||||
private:
|
||||
static constexpr const auto min_pool_size = 10U;
|
||||
|
||||
public:
|
||||
void execute(const std::string &client_id, std::uint64_t thread_id,
|
||||
const worker_callback &worker,
|
||||
|
@ -44,14 +44,16 @@ public:
|
||||
|
||||
explicit packet(data_buffer &&buffer) : buffer_(std::move(buffer)) {}
|
||||
|
||||
packet(const packet &p) noexcept = default;
|
||||
packet(const packet &pkt) noexcept = default;
|
||||
|
||||
packet(packet &&p) noexcept
|
||||
: buffer_(std::move(p.buffer_)), decode_offset_(p.decode_offset_) {}
|
||||
packet(packet &&pkt) noexcept
|
||||
: buffer_(std::move(pkt.buffer_)), decode_offset_(pkt.decode_offset_) {}
|
||||
|
||||
~packet() = default;
|
||||
|
||||
private:
|
||||
data_buffer buffer_;
|
||||
std::size_t decode_offset_ = 0u;
|
||||
std::size_t decode_offset_ = 0U;
|
||||
|
||||
public:
|
||||
[[nodiscard]] static auto decode_json(packet &response, json &json_data)
|
||||
@ -78,48 +80,46 @@ public:
|
||||
|
||||
[[nodiscard]] auto decode(void *&ptr) -> error_type;
|
||||
|
||||
[[nodiscard]] auto decode(std::int8_t &i) -> error_type;
|
||||
[[nodiscard]] auto decode(std::int8_t &val) -> error_type;
|
||||
|
||||
[[nodiscard]] auto decode(std::uint8_t &i) -> error_type;
|
||||
[[nodiscard]] auto decode(std::uint8_t &val) -> error_type;
|
||||
|
||||
[[nodiscard]] auto decode(std::int16_t &i) -> error_type;
|
||||
[[nodiscard]] auto decode(std::int16_t &val) -> error_type;
|
||||
|
||||
[[nodiscard]] auto decode(std::uint16_t &i) -> error_type;
|
||||
[[nodiscard]] auto decode(std::uint16_t &val) -> error_type;
|
||||
|
||||
[[nodiscard]] auto decode(std::int32_t &i) -> error_type;
|
||||
[[nodiscard]] auto decode(std::int32_t &val) -> error_type;
|
||||
|
||||
[[nodiscard]] auto decode(std::uint32_t &i) -> error_type;
|
||||
[[nodiscard]] auto decode(std::uint32_t &val) -> error_type;
|
||||
|
||||
[[nodiscard]] auto decode(std::int64_t &i) -> error_type;
|
||||
[[nodiscard]] auto decode(std::int64_t &val) -> error_type;
|
||||
|
||||
[[nodiscard]] auto decode(std::uint64_t &i) -> error_type;
|
||||
[[nodiscard]] auto decode(std::uint64_t &val) -> error_type;
|
||||
|
||||
[[nodiscard]] auto decode(remote::open_flags &i) -> error_type {
|
||||
return decode(reinterpret_cast<std::uint32_t &>(i));
|
||||
[[nodiscard]] auto decode(remote::open_flags &val) -> error_type {
|
||||
return decode(reinterpret_cast<std::uint32_t &>(val));
|
||||
}
|
||||
|
||||
[[nodiscard]] auto decode(remote::setattr_x &i) -> error_type;
|
||||
[[nodiscard]] auto decode(remote::setattr_x &val) -> error_type;
|
||||
|
||||
[[nodiscard]] auto decode(remote::stat &i) -> error_type;
|
||||
[[nodiscard]] auto decode(remote::stat &val) -> error_type;
|
||||
|
||||
[[nodiscard]] auto decode(remote::statfs &i) -> error_type;
|
||||
[[nodiscard]] auto decode(remote::statfs &val) -> error_type;
|
||||
|
||||
[[nodiscard]] auto decode(remote::statfs_x &i) -> error_type;
|
||||
[[nodiscard]] auto decode(remote::statfs_x &val) -> error_type;
|
||||
|
||||
[[nodiscard]] auto decode(remote::file_info &i) -> error_type;
|
||||
[[nodiscard]] auto decode(remote::file_info &val) -> error_type;
|
||||
|
||||
[[nodiscard]] auto decrypt(const std::string &token) -> error_type;
|
||||
|
||||
void encode(const void *buffer, std::size_t size, bool should_reserve = true);
|
||||
|
||||
void encode(char *str) { encode(std::string(str ? str : "")); }
|
||||
|
||||
void encode(const char *str) { encode(std::string(str ? str : "")); }
|
||||
void encode(const char *str) {
|
||||
encode(std::string(str == nullptr ? "" : str));
|
||||
}
|
||||
|
||||
void encode(const std::string &str);
|
||||
|
||||
void encode(wchar_t *str);
|
||||
|
||||
void encode(const wchar_t *str);
|
||||
|
||||
void encode(const std::wstring &str);
|
||||
@ -128,33 +128,35 @@ public:
|
||||
encode(static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(ptr)));
|
||||
}
|
||||
|
||||
void encode(std::int8_t i);
|
||||
void encode(std::int8_t val);
|
||||
|
||||
void encode(std::uint8_t i);
|
||||
void encode(std::uint8_t val);
|
||||
|
||||
void encode(std::int16_t i);
|
||||
void encode(std::int16_t val);
|
||||
|
||||
void encode(std::uint16_t i);
|
||||
void encode(std::uint16_t val);
|
||||
|
||||
void encode(std::int32_t i);
|
||||
void encode(std::int32_t val);
|
||||
|
||||
void encode(std::uint32_t i);
|
||||
void encode(std::uint32_t val);
|
||||
|
||||
void encode(std::int64_t i);
|
||||
void encode(std::int64_t val);
|
||||
|
||||
void encode(std::uint64_t i);
|
||||
void encode(std::uint64_t val);
|
||||
|
||||
void encode(remote::open_flags i) { encode(static_cast<std::uint32_t>(i)); }
|
||||
void encode(remote::open_flags val) {
|
||||
encode(static_cast<std::uint32_t>(val));
|
||||
}
|
||||
|
||||
void encode(remote::setattr_x i);
|
||||
void encode(remote::setattr_x val);
|
||||
|
||||
void encode(remote::stat i);
|
||||
void encode(remote::stat val);
|
||||
|
||||
void encode(remote::statfs i, bool should_reserve = true);
|
||||
void encode(remote::statfs val, bool should_reserve = true);
|
||||
|
||||
void encode(remote::statfs_x i);
|
||||
void encode(remote::statfs_x val);
|
||||
|
||||
void encode(remote::file_info i);
|
||||
void encode(remote::file_info val);
|
||||
|
||||
void encode_top(const void *buffer, std::size_t size,
|
||||
bool should_reserve = true);
|
||||
@ -168,35 +170,35 @@ public:
|
||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(ptr)));
|
||||
}
|
||||
|
||||
void encode_top(std::int8_t i);
|
||||
void encode_top(std::int8_t val);
|
||||
|
||||
void encode_top(std::uint8_t i);
|
||||
void encode_top(std::uint8_t val);
|
||||
|
||||
void encode_top(std::int16_t i);
|
||||
void encode_top(std::int16_t val);
|
||||
|
||||
void encode_top(std::uint16_t i);
|
||||
void encode_top(std::uint16_t val);
|
||||
|
||||
void encode_top(std::int32_t i);
|
||||
void encode_top(std::int32_t val);
|
||||
|
||||
void encode_top(std::uint32_t i);
|
||||
void encode_top(std::uint32_t val);
|
||||
|
||||
void encode_top(std::int64_t i);
|
||||
void encode_top(std::int64_t val);
|
||||
|
||||
void encode_top(std::uint64_t i);
|
||||
void encode_top(std::uint64_t val);
|
||||
|
||||
void encode_top(remote::open_flags i) {
|
||||
encode_top(static_cast<std::uint32_t>(i));
|
||||
void encode_top(remote::open_flags val) {
|
||||
encode_top(static_cast<std::uint32_t>(val));
|
||||
}
|
||||
|
||||
void encode_top(remote::setattr_x i);
|
||||
void encode_top(remote::setattr_x val);
|
||||
|
||||
void encode_top(remote::stat i);
|
||||
void encode_top(remote::stat val);
|
||||
|
||||
void encode_top(remote::statfs i, bool should_reserve = true);
|
||||
void encode_top(remote::statfs val, bool should_reserve = true);
|
||||
|
||||
void encode_top(remote::statfs_x i);
|
||||
void encode_top(remote::statfs_x val);
|
||||
|
||||
void encode_top(remote::file_info i);
|
||||
void encode_top(remote::file_info val);
|
||||
|
||||
void encrypt(const std::string &token);
|
||||
|
||||
@ -211,9 +213,9 @@ public:
|
||||
|
||||
auto operator=(data_buffer &&buffer) noexcept -> packet &;
|
||||
|
||||
auto operator=(const packet &p) noexcept -> packet &;
|
||||
auto operator=(const packet &pkt) noexcept -> packet &;
|
||||
|
||||
auto operator=(packet &&p) noexcept -> packet &;
|
||||
auto operator=(packet &&pkt) noexcept -> packet &;
|
||||
|
||||
[[nodiscard]] auto operator[](std::size_t index) -> char & {
|
||||
return buffer_[index];
|
||||
|
@ -1,177 +0,0 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef INCLUDE_COMM_S3_S3_COMM_HPP_
|
||||
#define INCLUDE_COMM_S3_S3_COMM_HPP_
|
||||
#if defined(REPERTORY_ENABLE_S3)
|
||||
|
||||
#include "comm/i_http_comm.hpp"
|
||||
#include "comm/i_s3_comm.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class app_config;
|
||||
|
||||
class s3_comm final : public i_s3_comm {
|
||||
public:
|
||||
explicit s3_comm(const app_config &config);
|
||||
s3_comm(s3_comm &&comm);
|
||||
|
||||
~s3_comm() override;
|
||||
|
||||
private:
|
||||
struct cache_entry final {
|
||||
std::chrono::system_clock::time_point expiration;
|
||||
directory_item_list items;
|
||||
|
||||
void reset_timeout(std::chrono::seconds timeout) {
|
||||
timeout = std::max(std::chrono::seconds(5u), timeout);
|
||||
expiration = std::chrono::system_clock::now() + timeout;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
const app_config &config_;
|
||||
s3_config s3_config_;
|
||||
std::unique_ptr<i_http_comm> s3_client_;
|
||||
|
||||
private:
|
||||
mutable std::recursive_mutex cached_directories_mutex_;
|
||||
mutable std::unordered_map<std::string, cache_entry> cached_directories_;
|
||||
|
||||
protected:
|
||||
bool active_ = true;
|
||||
|
||||
private:
|
||||
void clear_expired_directories();
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_cached_directory_item_count(const std::string &api_path,
|
||||
std::size_t &count) const -> bool;
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_cached_directory_items(const std::string &api_path,
|
||||
meta_provider_callback meta_provider,
|
||||
directory_item_list &list) const -> bool;
|
||||
|
||||
[[nodiscard]] auto get_cached_file_exists(const std::string &api_path) const
|
||||
-> bool;
|
||||
|
||||
[[nodiscard]] auto grab_directory_items(const std::string &api_path,
|
||||
meta_provider_callback meta_provider,
|
||||
directory_item_list &list) const
|
||||
-> api_error;
|
||||
|
||||
void raise_begin(const std::string &function_name,
|
||||
const std::string &api_path) const;
|
||||
|
||||
[[nodiscard]] auto raise_end(const std::string &function_name,
|
||||
const std::string &api_path,
|
||||
const api_error &error, long code) const
|
||||
-> api_error;
|
||||
|
||||
void remove_cached_directory(const std::string &api_path);
|
||||
|
||||
void set_cached_directory_items(const std::string &api_path,
|
||||
directory_item_list list) const;
|
||||
|
||||
public:
|
||||
[[nodiscard]] auto create_directory(const std::string &api_path)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto directory_exists(const std::string &api_path) const
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto file_exists(const std::string &api_path,
|
||||
const get_key_callback &get_key) const
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_directory_item_count(const std::string &api_path,
|
||||
meta_provider_callback meta_provider) const
|
||||
-> std::size_t override;
|
||||
|
||||
[[nodiscard]] auto get_directory_items(const std::string &api_path,
|
||||
meta_provider_callback meta_provider,
|
||||
directory_item_list &list) const
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto get_directory_list(api_file_list &list) const
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto get_file(const std::string &api_path,
|
||||
const get_key_callback &get_key,
|
||||
const get_name_callback &get_name,
|
||||
const get_token_callback &get_token,
|
||||
api_file &file) const -> api_error override;
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_file_list(const get_api_file_token_callback &get_api_file_token,
|
||||
const get_name_callback &get_name, api_file_list &list) const
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto get_object_list(std::vector<directory_item> &list) const
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto get_object_name(const std::string &api_path,
|
||||
const get_key_callback &getKey) const
|
||||
-> std::string override;
|
||||
|
||||
[[nodiscard]] auto get_s3_config() -> s3_config override {
|
||||
return s3_config_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_s3_config() const -> s3_config override {
|
||||
return s3_config_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_online() const -> bool override {
|
||||
// TODO implement this
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto read_file_bytes(
|
||||
const std::string &api_path, std::size_t size, std::uint64_t offset,
|
||||
data_buffer &data, const get_key_callback &get_key,
|
||||
const get_size_callback &get_size, const get_token_callback &get_token,
|
||||
stop_type &stop_requested) const -> api_error override;
|
||||
|
||||
[[nodiscard]] auto remove_directory(const std::string &api_path)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto remove_file(const std::string &api_path,
|
||||
const get_key_callback &get_key)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto rename_file(const std::string &api_path,
|
||||
const std::string &new_api_path)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto
|
||||
upload_file(const std::string &api_path, const std::string &source_path,
|
||||
const std::string &encryption_token,
|
||||
const get_key_callback &get_key, const set_key_callback &set_key,
|
||||
stop_type &stop_requested) -> api_error override;
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // REPERTORY_ENABLE_S3
|
||||
#endif // INCLUDE_COMM_S3_S3_COMM_HPP_
|
@ -59,11 +59,6 @@
|
||||
#include <sys/mount.h>
|
||||
#include <sys/statvfs.h>
|
||||
#endif
|
||||
#if __linux__
|
||||
#include <utils/uuid++.hh>
|
||||
#else
|
||||
#include <uuid/uuid.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
@ -82,7 +77,6 @@
|
||||
#include <optional>
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
@ -90,6 +84,14 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <sodium.h>
|
||||
template <typename data_type>
|
||||
[[nodiscard]] inline auto repertory_rand() -> data_type {
|
||||
data_type ret{};
|
||||
randombytes_buf(&ret, sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
#include <boost/archive/text_iarchive.hpp>
|
||||
#include <boost/archive/text_oarchive.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
@ -102,6 +104,7 @@
|
||||
#include <curl/multi.h>
|
||||
#include <json.hpp>
|
||||
#include <rocksdb/db.h>
|
||||
#include <stduuid.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <sddl.h>
|
||||
@ -116,7 +119,6 @@
|
||||
#endif
|
||||
|
||||
#include <pugixml.hpp>
|
||||
#include <sodium.h>
|
||||
|
||||
#define CPPHTTPLIB_TCP_NODELAY true
|
||||
#define CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
@ -136,12 +138,12 @@ using json = nlohmann::json;
|
||||
#define REPERTORY_API_INVALID_HANDLE static_cast<std::uint64_t>(-1)
|
||||
using native_handle = HANDLE;
|
||||
#else
|
||||
#define REPERTORY_INVALID_HANDLE -1
|
||||
#define REPERTORY_INVALID_HANDLE (-1)
|
||||
#define REPERTORY_API_INVALID_HANDLE REPERTORY_INVALID_HANDLE
|
||||
using native_handle = int;
|
||||
#endif
|
||||
|
||||
#define NANOS_PER_SECOND 1000000000L
|
||||
constexpr const auto NANOS_PER_SECOND = 1000000000L;
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef CreateDirectory
|
||||
@ -339,6 +341,7 @@ using WCHAR = wchar_t;
|
||||
#define STATUS_OBJECT_NAME_NOT_FOUND std::int32_t(0xC0000034L)
|
||||
#define STATUS_OBJECT_PATH_INVALID std::int32_t(0xC0000039L)
|
||||
#define STATUS_UNEXPECTED_IO_ERROR std::int32_t(0xC00000E9L)
|
||||
|
||||
#define CONVERT_STATUS_NOT_IMPLEMENTED(e) \
|
||||
((std::int32_t(e) == STATUS_NOT_IMPLEMENTED) ? -ENOTSUP : e)
|
||||
|
||||
|
@ -1,117 +0,0 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef INCLUDE_DB_DIRECTORY_DB_HPP_
|
||||
#define INCLUDE_DB_DIRECTORY_DB_HPP_
|
||||
|
||||
#include "app_config.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/rocksdb_utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class directory_db final {
|
||||
private:
|
||||
class directory_tree final {
|
||||
private:
|
||||
std::unordered_map<std::string, std::vector<std::string>>
|
||||
sub_directory_lookup_;
|
||||
|
||||
public:
|
||||
void add_path(const std::string &api_path,
|
||||
const std::vector<std::string> &files, rocksdb::DB &db);
|
||||
|
||||
[[nodiscard]] auto get_count(const std::string &api_path) const
|
||||
-> std::size_t;
|
||||
|
||||
[[nodiscard]] auto get_directories() const -> std::vector<std::string>;
|
||||
|
||||
[[nodiscard]] auto get_sub_directories(const std::string &api_path) const
|
||||
-> std::vector<std::string>;
|
||||
|
||||
[[nodiscard]] auto is_directory(const std::string &api_path) const -> bool;
|
||||
|
||||
void remove_directory(const std::string &api_path, rocksdb::DB &db,
|
||||
bool allow_remove_root = false);
|
||||
};
|
||||
|
||||
public:
|
||||
explicit directory_db(const app_config &config);
|
||||
|
||||
public:
|
||||
~directory_db();
|
||||
|
||||
private:
|
||||
mutable std::recursive_mutex directory_mutex_;
|
||||
std::unique_ptr<rocksdb::DB> db_;
|
||||
directory_tree tree_;
|
||||
const std::string DIRDB_NAME = "directory_db";
|
||||
|
||||
private:
|
||||
[[nodiscard]] auto get_directory_data(const std::string &api_path) const
|
||||
-> json;
|
||||
|
||||
public:
|
||||
[[nodiscard]] auto create_directory(const std::string &api_path,
|
||||
bool create_always = false) -> api_error;
|
||||
|
||||
[[nodiscard]] auto create_file(const std::string &api_path) -> api_error;
|
||||
|
||||
[[nodiscard]] auto get_directory_item_count(const std::string &api_path) const
|
||||
-> std::uint64_t;
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_file(const std::string &api_path, api_file &file,
|
||||
api_file_provider_callback api_file_provider) const -> api_error;
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_file_list(api_file_list &list,
|
||||
api_file_provider_callback api_file_provider) const
|
||||
-> api_error;
|
||||
|
||||
[[nodiscard]] auto get_sub_directory_count(const std::string &api_path) const
|
||||
-> std::size_t;
|
||||
|
||||
[[nodiscard]] auto get_total_item_count() const -> std::uint64_t;
|
||||
|
||||
[[nodiscard]] auto is_directory(const std::string &api_path) const -> bool;
|
||||
|
||||
[[nodiscard]] auto is_file(const std::string &api_path) const -> bool;
|
||||
|
||||
void populate_directory_files(const std::string &api_path,
|
||||
meta_provider_callback meta_provider,
|
||||
directory_item_list &list) const;
|
||||
|
||||
void populate_sub_directories(const std::string &api_path,
|
||||
meta_provider_callback meta_provider,
|
||||
directory_item_list &list) const;
|
||||
|
||||
[[nodiscard]] auto remove_directory(const std::string &api_path,
|
||||
bool allow_remove_root = false)
|
||||
-> api_error;
|
||||
|
||||
[[nodiscard]] auto remove_file(const std::string &api_path) -> bool;
|
||||
|
||||
[[nodiscard]] auto rename_file(const std::string &from_api_path,
|
||||
const std::string &to_api_path) -> api_error;
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // INCLUDE_DB_DIRECTORY_DB_HPP_
|
@ -1,109 +0,0 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef INCLUDE_DB_META_DB_HPP_
|
||||
#define INCLUDE_DB_META_DB_HPP_
|
||||
|
||||
#include "app_config.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/rocksdb_utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class meta_db final {
|
||||
public:
|
||||
explicit meta_db(const app_config &config);
|
||||
|
||||
public:
|
||||
~meta_db();
|
||||
|
||||
private:
|
||||
std::unique_ptr<rocksdb::DB> db_;
|
||||
rocksdb::ColumnFamilyHandle *default_family_{};
|
||||
rocksdb::ColumnFamilyHandle *source_family_{};
|
||||
rocksdb::ColumnFamilyHandle *keys_family_{};
|
||||
const std::string METADB_NAME = "meta_db";
|
||||
|
||||
private:
|
||||
[[nodiscard]] auto
|
||||
perform_action(const std::string &function_name,
|
||||
const std::function<rocksdb::Status()> &action) const
|
||||
-> api_error;
|
||||
|
||||
[[nodiscard]] auto get_item_meta_json(const std::string &api_path,
|
||||
json &json_data) const -> api_error;
|
||||
|
||||
[[nodiscard]] auto store_item_meta(const std::string &api_path,
|
||||
const std::string &key,
|
||||
const std::string &value) -> api_error;
|
||||
|
||||
public:
|
||||
[[nodiscard]] auto create_iterator(bool source_family) const
|
||||
-> std::shared_ptr<rocksdb::Iterator>;
|
||||
|
||||
[[nodiscard]] auto get_api_path_from_key(const std::string &key,
|
||||
std::string &api_path) const
|
||||
-> api_error;
|
||||
|
||||
[[nodiscard]] auto get_api_path_from_source(const std::string &source_path,
|
||||
std::string &api_path) const
|
||||
-> api_error;
|
||||
|
||||
[[nodiscard]] auto get_item_meta(const std::string &api_path,
|
||||
api_meta_map &meta) const -> api_error;
|
||||
|
||||
[[nodiscard]] auto get_item_meta(const std::string &api_path,
|
||||
const std::string &key,
|
||||
std::string &value) const -> api_error;
|
||||
|
||||
[[nodiscard]] auto get_item_meta_exists(const std::string &api_path) const
|
||||
-> bool;
|
||||
|
||||
[[nodiscard]] auto get_total_item_count() const -> std::uint64_t;
|
||||
|
||||
[[nodiscard]] auto get_pinned_files() const -> std::vector<std::string>;
|
||||
|
||||
[[nodiscard]] auto
|
||||
get_source_path_exists(const std::string &source_path) const -> bool;
|
||||
|
||||
[[nodiscard]] auto remove_item_meta(const std::string &api_path) -> api_error;
|
||||
|
||||
[[nodiscard]] auto remove_item_meta(const std::string &api_path,
|
||||
const std::string &key) -> api_error;
|
||||
|
||||
[[nodiscard]] auto rename_item_meta(const std::string &source_path,
|
||||
const std::string &from_api_path,
|
||||
const std::string &to_api_path)
|
||||
-> api_error;
|
||||
|
||||
[[nodiscard]] auto set_item_meta(const std::string &api_path,
|
||||
const std::string &key,
|
||||
const std::string &value) -> api_error;
|
||||
|
||||
[[nodiscard]] auto set_item_meta(const std::string &api_path,
|
||||
const api_meta_map &meta) -> api_error;
|
||||
|
||||
[[nodiscard]] auto set_source_path(const std::string &api_path,
|
||||
const std::string &source_path)
|
||||
-> api_error;
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // INCLUDE_DB_META_DB_HPP_
|
@ -27,12 +27,12 @@
|
||||
#include "file_manager/file_manager.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class i_provider;
|
||||
class app_config;
|
||||
class console_consumer;
|
||||
class directory_cache;
|
||||
class eviction;
|
||||
class full_server;
|
||||
class i_provider;
|
||||
class lock_data;
|
||||
class logging_consumer;
|
||||
namespace remote_fuse {
|
||||
@ -45,6 +45,13 @@ public:
|
||||
|
||||
~fuse_drive() override = default;
|
||||
|
||||
public:
|
||||
fuse_drive(const fuse_drive &) = delete;
|
||||
fuse_drive(fuse_drive &&) = delete;
|
||||
|
||||
auto operator=(const fuse_drive &) -> fuse_drive & = delete;
|
||||
auto operator=(fuse_drive &&) -> fuse_drive & = delete;
|
||||
|
||||
private:
|
||||
lock_data &lock_data_;
|
||||
i_provider &provider_;
|
||||
@ -69,7 +76,7 @@ protected:
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
[[nodiscard]] auto chmod_impl(std::string api_path, mode_t mode,
|
||||
struct fuse_file_info *fi)
|
||||
struct fuse_file_info *file_info)
|
||||
-> api_error override;
|
||||
#else
|
||||
[[nodiscard]] auto chmod_impl(std::string api_path, mode_t mode)
|
||||
@ -78,7 +85,7 @@ protected:
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
[[nodiscard]] auto chown_impl(std::string api_path, uid_t uid, gid_t gid,
|
||||
struct fuse_file_info *fi)
|
||||
struct fuse_file_info *file_info)
|
||||
-> api_error override;
|
||||
#else
|
||||
[[nodiscard]] auto chown_impl(std::string api_path, uid_t uid, gid_t gid)
|
||||
@ -86,40 +93,40 @@ protected:
|
||||
#endif
|
||||
|
||||
[[nodiscard]] auto create_impl(std::string api_path, mode_t mode,
|
||||
struct fuse_file_info *fi)
|
||||
struct fuse_file_info *file_info)
|
||||
-> api_error override;
|
||||
|
||||
void destroy_impl(void *ptr) override;
|
||||
|
||||
[[nodiscard]] auto fallocate_impl(std::string api_path, int mode,
|
||||
off_t offset, off_t length,
|
||||
struct fuse_file_info *fi)
|
||||
struct fuse_file_info *file_info)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto fgetattr_impl(std::string api_path, struct stat *st,
|
||||
struct fuse_file_info *fi)
|
||||
struct fuse_file_info *file_info)
|
||||
-> api_error override;
|
||||
|
||||
#ifdef __APPLE__
|
||||
[[nodiscard]] auto fsetattr_x_impl(std::string api_path,
|
||||
struct setattr_x *attr,
|
||||
struct fuse_file_info *fi)
|
||||
struct fuse_file_info *file_info)
|
||||
-> api_error override;
|
||||
#endif // __APPLE__
|
||||
|
||||
[[nodiscard]] auto fsync_impl(std::string api_path, int datasync,
|
||||
struct fuse_file_info *fi)
|
||||
struct fuse_file_info *file_info)
|
||||
-> api_error override;
|
||||
|
||||
#if FUSE_USE_VERSION < 30
|
||||
[[nodiscard]] auto ftruncate_impl(std::string api_path, off_t size,
|
||||
struct fuse_file_info *fi)
|
||||
struct fuse_file_info *file_info)
|
||||
-> api_error override;
|
||||
#endif
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
[[nodiscard]] auto getattr_impl(std::string api_path, struct stat *st,
|
||||
struct fuse_file_info *fi)
|
||||
struct fuse_file_info *file_info)
|
||||
-> api_error override;
|
||||
#else
|
||||
[[nodiscard]] auto getattr_impl(std::string api_path, struct stat *st)
|
||||
@ -145,37 +152,38 @@ protected:
|
||||
|
||||
void notify_fuse_main_exit(int &ret) override;
|
||||
|
||||
[[nodiscard]] auto open_impl(std::string api_path, struct fuse_file_info *fi)
|
||||
[[nodiscard]] auto open_impl(std::string api_path,
|
||||
struct fuse_file_info *file_info)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto opendir_impl(std::string api_path,
|
||||
struct fuse_file_info *fi)
|
||||
struct fuse_file_info *file_info)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto read_impl(std::string api_path, char *buffer,
|
||||
size_t read_size, off_t read_offset,
|
||||
struct fuse_file_info *fi,
|
||||
struct fuse_file_info *file_info,
|
||||
std::size_t &bytes_read) -> api_error override;
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
[[nodiscard]] auto readdir_impl(std::string api_path, void *buf,
|
||||
fuse_fill_dir_t fuse_fill_dir, off_t offset,
|
||||
struct fuse_file_info *fi,
|
||||
struct fuse_file_info *file_info,
|
||||
fuse_readdir_flags flags)
|
||||
-> api_error override;
|
||||
#else
|
||||
[[nodiscard]] auto readdir_impl(std::string api_path, void *buf,
|
||||
fuse_fill_dir_t fuse_fill_dir, off_t offset,
|
||||
struct fuse_file_info *fi)
|
||||
struct fuse_file_info *file_info)
|
||||
-> api_error override;
|
||||
#endif
|
||||
|
||||
[[nodiscard]] auto release_impl(std::string api_path,
|
||||
struct fuse_file_info *fi)
|
||||
struct fuse_file_info *file_info)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto releasedir_impl(std::string api_path,
|
||||
struct fuse_file_info *fi)
|
||||
struct fuse_file_info *file_info)
|
||||
-> api_error override;
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
@ -197,8 +205,7 @@ protected:
|
||||
|
||||
#ifdef __APPLE__
|
||||
[[nodiscard]] auto getxattr_impl(std::string api_path, const char *name,
|
||||
char *value, size_t size,
|
||||
[[nodiscard]] uint32_t position,
|
||||
char *value, size_t size, uint32_t position,
|
||||
int &attribute_size) -> api_error override;
|
||||
#else // __APPLE__
|
||||
[[nodiscard]] auto getxattr_impl(std::string api_path, const char *name,
|
||||
@ -252,7 +259,7 @@ protected:
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
[[nodiscard]] auto truncate_impl(std::string api_path, off_t size,
|
||||
struct fuse_file_info *fi)
|
||||
struct fuse_file_info *file_info)
|
||||
-> api_error override;
|
||||
#else
|
||||
[[nodiscard]] auto truncate_impl(std::string api_path, off_t size)
|
||||
@ -264,7 +271,7 @@ protected:
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
[[nodiscard]] auto utimens_impl(std::string api_path,
|
||||
const struct timespec tv[2],
|
||||
struct fuse_file_info *fi)
|
||||
struct fuse_file_info *file_info)
|
||||
-> api_error override;
|
||||
#else
|
||||
[[nodiscard]] auto utimens_impl(std::string api_path,
|
||||
@ -274,7 +281,7 @@ protected:
|
||||
|
||||
[[nodiscard]] auto write_impl(std::string api_path, const char *buffer,
|
||||
size_t write_size, off_t write_offset,
|
||||
struct fuse_file_info *fi,
|
||||
struct fuse_file_info *file_info,
|
||||
std::size_t &bytes_written)
|
||||
-> api_error override;
|
||||
|
||||
@ -309,7 +316,8 @@ public:
|
||||
[[nodiscard]] auto is_processing(const std::string &api_path) const
|
||||
-> bool override;
|
||||
|
||||
void populate_stat(const directory_item &di, struct stat &st) const override;
|
||||
void populate_stat(const directory_item &dir_item,
|
||||
struct stat &st) const override;
|
||||
|
||||
[[nodiscard]] auto rename_directory(const std::string &from_api_path,
|
||||
const std::string &to_api_path)
|
||||
|
@ -69,7 +69,7 @@ public:
|
||||
[[nodiscard]] virtual auto is_processing(const std::string &api_path) const
|
||||
-> bool = 0;
|
||||
|
||||
virtual void populate_stat(const directory_item &di,
|
||||
virtual void populate_stat(const directory_item &dir_item,
|
||||
struct stat &st) const = 0;
|
||||
|
||||
[[nodiscard]] virtual auto rename_directory(const std::string &from_api_path,
|
||||
|
@ -237,12 +237,12 @@ public:
|
||||
}
|
||||
|
||||
[[nodiscard]] auto json_create_directory_snapshot(const std::string &path,
|
||||
json &jsonData)
|
||||
json &json_data)
|
||||
-> packet::error_type override;
|
||||
|
||||
[[nodiscard]] auto json_read_directory_snapshot(
|
||||
const std::string &path, const remote::file_handle &handle,
|
||||
std::uint32_t page, json &jsonData) -> packet::error_type override;
|
||||
std::uint32_t page, json &json_data) -> packet::error_type override;
|
||||
|
||||
[[nodiscard]] auto
|
||||
json_release_directory_snapshot(const std::string &path,
|
||||
@ -254,7 +254,7 @@ public:
|
||||
-> packet::error_type override;
|
||||
|
||||
[[nodiscard]] auto winfsp_cleanup(PVOID file_desc, PWSTR file_name,
|
||||
UINT32 flags, BOOLEAN &wasClosed)
|
||||
UINT32 flags, BOOLEAN &was_closed)
|
||||
-> packet::error_type override;
|
||||
|
||||
[[nodiscard]] auto winfsp_close(PVOID file_desc)
|
||||
@ -275,8 +275,8 @@ public:
|
||||
|
||||
[[nodiscard]] auto
|
||||
winfsp_get_security_by_name(PWSTR file_name, PUINT32 attributes,
|
||||
std::uint64_t * /*securityDescriptorSize*/,
|
||||
std::wstring & /*strDescriptor*/)
|
||||
std::uint64_t * /*security_descriptor_size*/,
|
||||
std::wstring & /*str_descriptor*/)
|
||||
-> packet::error_type override;
|
||||
|
||||
[[nodiscard]] auto winfsp_get_volume_info(UINT64 &total_size,
|
||||
@ -317,7 +317,7 @@ public:
|
||||
UINT64 last_access_time, UINT64 last_write_time, UINT64 change_time,
|
||||
remote::file_info *file_info) -> packet::error_type override;
|
||||
|
||||
[[nodiscard]] auto winfsp_set_file_size(PVOID file_desc, UINT64 newSize,
|
||||
[[nodiscard]] auto winfsp_set_file_size(PVOID file_desc, UINT64 new_size,
|
||||
BOOLEAN set_allocation_size,
|
||||
remote::file_info *file_info)
|
||||
-> packet::error_type override;
|
||||
|
@ -44,9 +44,15 @@ class remote_server_base : public remote_open_file_table,
|
||||
public virtual remote_winfsp::i_remote_instance,
|
||||
public virtual remote_fuse::i_remote_instance {
|
||||
public:
|
||||
remote_server_base(app_config &config, drive &d, std::string mount_location)
|
||||
remote_server_base(const remote_server_base &) = delete;
|
||||
remote_server_base(remote_server_base &&) = delete;
|
||||
auto operator=(const remote_server_base &) -> remote_server_base & = delete;
|
||||
auto operator=(remote_server_base &&) -> remote_server_base & = delete;
|
||||
|
||||
public:
|
||||
remote_server_base(app_config &config, drive &drv, std::string mount_location)
|
||||
: config_(config),
|
||||
drive_(d),
|
||||
drive_(drv),
|
||||
mount_location_(std::move(mount_location)),
|
||||
client_pool_(config.get_remote_client_pool_size()) {
|
||||
event_system::instance().raise<service_started>("remote_server_base");
|
||||
@ -57,14 +63,13 @@ public:
|
||||
packet &) -> packet::error_type {
|
||||
auto ret = STATUS_SUCCESS;
|
||||
|
||||
HANDLE file_desc;
|
||||
HANDLE file_desc{};
|
||||
DECODE_OR_RETURN(request, file_desc);
|
||||
|
||||
std::wstring file_name;
|
||||
DECODE_OR_RETURN(request, file_name);
|
||||
|
||||
ret = this->winfsp_can_delete(file_desc, &file_name[0]);
|
||||
return ret;
|
||||
return this->winfsp_can_delete(file_desc, file_name.data());
|
||||
}});
|
||||
handler_lookup_.insert(
|
||||
{"::winfsp_cleanup",
|
||||
@ -73,17 +78,17 @@ public:
|
||||
packet &response) -> packet::error_type {
|
||||
auto ret = STATUS_SUCCESS;
|
||||
|
||||
HANDLE file_desc;
|
||||
HANDLE file_desc{};
|
||||
DECODE_OR_RETURN(request, file_desc);
|
||||
|
||||
std::wstring file_name;
|
||||
DECODE_OR_RETURN(request, file_name);
|
||||
|
||||
UINT32 flags;
|
||||
UINT32 flags{};
|
||||
DECODE_OR_RETURN(request, flags);
|
||||
|
||||
BOOLEAN was_closed;
|
||||
ret = this->winfsp_cleanup(file_desc, &file_name[0], flags,
|
||||
BOOLEAN was_closed{};
|
||||
ret = this->winfsp_cleanup(file_desc, file_name.data(), flags,
|
||||
was_closed);
|
||||
response.encode(was_closed);
|
||||
|
||||
@ -96,11 +101,10 @@ public:
|
||||
packet &) -> packet::error_type {
|
||||
auto ret = STATUS_SUCCESS;
|
||||
|
||||
HANDLE file_desc;
|
||||
HANDLE file_desc{};
|
||||
DECODE_OR_RETURN(request, file_desc);
|
||||
|
||||
ret = this->winfsp_close(file_desc);
|
||||
return ret;
|
||||
return this->winfsp_close(file_desc);
|
||||
}});
|
||||
handler_lookup_.insert(
|
||||
{"::winfsp_create",
|
||||
@ -112,23 +116,23 @@ public:
|
||||
std::wstring file_name;
|
||||
DECODE_OR_RETURN(request, file_name);
|
||||
|
||||
UINT32 create_options;
|
||||
UINT32 create_options{};
|
||||
DECODE_OR_RETURN(request, create_options);
|
||||
|
||||
UINT32 granted_access;
|
||||
UINT32 granted_access{};
|
||||
DECODE_OR_RETURN(request, granted_access);
|
||||
|
||||
UINT32 attributes;
|
||||
UINT32 attributes{};
|
||||
DECODE_OR_RETURN(request, attributes);
|
||||
|
||||
UINT64 allocation_size;
|
||||
UINT64 allocation_size{};
|
||||
DECODE_OR_RETURN(request, allocation_size);
|
||||
|
||||
BOOLEAN exists = 0;
|
||||
BOOLEAN exists{0};
|
||||
remote::file_info file_info{};
|
||||
std::string normalized_name;
|
||||
PVOID file_desc;
|
||||
ret = this->winfsp_create(&file_name[0], create_options,
|
||||
PVOID file_desc{};
|
||||
ret = this->winfsp_create(file_name.data(), create_options,
|
||||
granted_access, attributes,
|
||||
allocation_size, &file_desc, &file_info,
|
||||
normalized_name, exists);
|
||||
@ -136,8 +140,10 @@ public:
|
||||
#ifdef _WIN32
|
||||
this->set_client_id(file_desc, client_id);
|
||||
#else
|
||||
this->set_client_id(reinterpret_cast<std::uintptr_t>(file_desc),
|
||||
client_id);
|
||||
this->set_client_id(
|
||||
static_cast<native_handle>(
|
||||
reinterpret_cast<std::uintptr_t>(file_desc)),
|
||||
client_id);
|
||||
#endif
|
||||
response.encode(file_desc);
|
||||
response.encode(file_info);
|
||||
@ -154,7 +160,7 @@ public:
|
||||
packet &response) -> packet::error_type {
|
||||
auto ret = STATUS_SUCCESS;
|
||||
|
||||
HANDLE file_desc;
|
||||
HANDLE file_desc{};
|
||||
DECODE_OR_RETURN(request, file_desc);
|
||||
|
||||
remote::file_info file_info{};
|
||||
@ -172,7 +178,7 @@ public:
|
||||
packet &response) -> packet::error_type {
|
||||
auto ret = STATUS_SUCCESS;
|
||||
|
||||
HANDLE file_desc;
|
||||
HANDLE file_desc{};
|
||||
DECODE_OR_RETURN(request, file_desc);
|
||||
|
||||
remote::file_info file_info{};
|
||||
@ -192,21 +198,22 @@ public:
|
||||
std::wstring file_name;
|
||||
DECODE_OR_RETURN(request, file_name);
|
||||
|
||||
std::uint64_t descriptor_size;
|
||||
std::uint64_t descriptor_size{};
|
||||
DECODE_OR_RETURN(request, descriptor_size);
|
||||
|
||||
std::uint8_t get_attributes;
|
||||
std::uint8_t get_attributes{};
|
||||
DECODE_OR_RETURN(request, get_attributes);
|
||||
|
||||
UINT32 attributes;
|
||||
auto *attrPtr = get_attributes ? &attributes : nullptr;
|
||||
UINT32 attributes{};
|
||||
auto *attr_ptr = get_attributes == 0U ? nullptr : &attributes;
|
||||
std::wstring string_descriptor;
|
||||
ret = this->winfsp_get_security_by_name(
|
||||
&file_name[0], attrPtr,
|
||||
descriptor_size ? &descriptor_size : nullptr, string_descriptor);
|
||||
file_name.data(), attr_ptr,
|
||||
descriptor_size == 0U ? nullptr : &descriptor_size,
|
||||
string_descriptor);
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
response.encode(string_descriptor);
|
||||
if (get_attributes) {
|
||||
if (get_attributes != 0U) {
|
||||
response.encode(attributes);
|
||||
}
|
||||
}
|
||||
@ -219,8 +226,8 @@ public:
|
||||
packet &response) -> packet::error_type {
|
||||
auto ret = STATUS_SUCCESS;
|
||||
|
||||
UINT64 total_size = 0u;
|
||||
UINT64 free_size = 0u;
|
||||
UINT64 total_size{};
|
||||
UINT64 free_size{};
|
||||
std::string volume_label;
|
||||
if ((ret = this->winfsp_get_volume_info(
|
||||
total_size, free_size, volume_label)) ==
|
||||
@ -257,24 +264,26 @@ public:
|
||||
std::wstring file_name;
|
||||
DECODE_OR_RETURN(request, file_name);
|
||||
|
||||
UINT32 create_options;
|
||||
UINT32 create_options{};
|
||||
DECODE_OR_RETURN(request, create_options);
|
||||
|
||||
UINT32 granted_access;
|
||||
UINT32 granted_access{};
|
||||
DECODE_OR_RETURN(request, granted_access);
|
||||
|
||||
remote::file_info file_info{};
|
||||
std::string normalized_name;
|
||||
PVOID file_desc;
|
||||
ret =
|
||||
this->winfsp_open(&file_name[0], create_options, granted_access,
|
||||
&file_desc, &file_info, normalized_name);
|
||||
PVOID file_desc{};
|
||||
ret = this->winfsp_open(file_name.data(), create_options,
|
||||
granted_access, &file_desc, &file_info,
|
||||
normalized_name);
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
#ifdef _WIN32
|
||||
this->set_client_id(file_desc, client_id);
|
||||
#else
|
||||
this->set_client_id(reinterpret_cast<std::uintptr_t>(file_desc),
|
||||
client_id);
|
||||
this->set_client_id(
|
||||
static_cast<native_handle>(
|
||||
reinterpret_cast<std::uintptr_t>(file_desc)),
|
||||
client_id);
|
||||
#endif
|
||||
response.encode(file_desc);
|
||||
response.encode(file_info);
|
||||
@ -290,16 +299,16 @@ public:
|
||||
packet &response) -> packet::error_type {
|
||||
auto ret = STATUS_SUCCESS;
|
||||
|
||||
HANDLE file_desc;
|
||||
HANDLE file_desc{};
|
||||
DECODE_OR_RETURN(request, file_desc);
|
||||
|
||||
UINT32 attributes;
|
||||
UINT32 attributes{};
|
||||
DECODE_OR_RETURN(request, attributes);
|
||||
|
||||
BOOLEAN replace_attributes;
|
||||
BOOLEAN replace_attributes{};
|
||||
DECODE_OR_RETURN(request, replace_attributes);
|
||||
|
||||
UINT64 allocation_size;
|
||||
UINT64 allocation_size{};
|
||||
DECODE_OR_RETURN(request, allocation_size);
|
||||
|
||||
remote::file_info file_info{};
|
||||
@ -318,23 +327,23 @@ public:
|
||||
packet &response) -> packet::error_type {
|
||||
auto ret = STATUS_SUCCESS;
|
||||
|
||||
HANDLE file_desc;
|
||||
HANDLE file_desc{};
|
||||
DECODE_OR_RETURN(request, file_desc);
|
||||
|
||||
UINT64 offset;
|
||||
UINT64 offset{};
|
||||
DECODE_OR_RETURN(request, offset);
|
||||
|
||||
UINT32 length;
|
||||
UINT32 length{};
|
||||
DECODE_OR_RETURN(request, length);
|
||||
|
||||
data_buffer buffer(length);
|
||||
UINT32 bytes_transferred = 0;
|
||||
ret = this->winfsp_read(file_desc, &buffer[0], offset, length,
|
||||
ret = this->winfsp_read(file_desc, buffer.data(), offset, length,
|
||||
&bytes_transferred);
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
response.encode(static_cast<UINT32>(bytes_transferred));
|
||||
if (bytes_transferred) {
|
||||
response.encode(&buffer[0], bytes_transferred);
|
||||
if (bytes_transferred != 0U) {
|
||||
response.encode(buffer.data(), bytes_transferred);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@ -346,7 +355,7 @@ public:
|
||||
packet &response) -> packet::error_type {
|
||||
auto ret = STATUS_SUCCESS;
|
||||
|
||||
HANDLE file_desc;
|
||||
HANDLE file_desc{};
|
||||
DECODE_OR_RETURN(request, file_desc);
|
||||
|
||||
std::wstring pattern;
|
||||
@ -355,13 +364,14 @@ public:
|
||||
std::wstring marker;
|
||||
DECODE_OR_IGNORE(request, marker);
|
||||
|
||||
json itemList;
|
||||
json item_list;
|
||||
ret = this->winfsp_read_directory(
|
||||
file_desc, &pattern[0],
|
||||
wcsnlen(&marker[0], marker.size()) ? &marker[0] : nullptr,
|
||||
itemList);
|
||||
file_desc, pattern.data(),
|
||||
wcsnlen(marker.data(), marker.size()) == 0U ? nullptr
|
||||
: marker.data(),
|
||||
item_list);
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
response.encode(itemList.dump(0));
|
||||
response.encode(item_list.dump(0));
|
||||
}
|
||||
return ret;
|
||||
}});
|
||||
@ -372,7 +382,7 @@ public:
|
||||
packet &) -> packet::error_type {
|
||||
auto ret = STATUS_SUCCESS;
|
||||
|
||||
HANDLE file_desc;
|
||||
HANDLE file_desc{};
|
||||
DECODE_OR_RETURN(request, file_desc);
|
||||
|
||||
std::wstring file_name;
|
||||
@ -381,11 +391,11 @@ public:
|
||||
std::wstring new_file_name;
|
||||
DECODE_OR_RETURN(request, new_file_name);
|
||||
|
||||
BOOLEAN replace_if_exists;
|
||||
BOOLEAN replace_if_exists{};
|
||||
DECODE_OR_RETURN(request, replace_if_exists);
|
||||
|
||||
ret = this->winfsp_rename(file_desc, &file_name[0],
|
||||
&new_file_name[0], replace_if_exists);
|
||||
ret = this->winfsp_rename(file_desc, file_name.data(),
|
||||
new_file_name.data(), replace_if_exists);
|
||||
return ret;
|
||||
}});
|
||||
handler_lookup_.insert(
|
||||
@ -395,22 +405,22 @@ public:
|
||||
packet &response) -> packet::error_type {
|
||||
auto ret = STATUS_SUCCESS;
|
||||
|
||||
HANDLE file_desc;
|
||||
HANDLE file_desc{};
|
||||
DECODE_OR_RETURN(request, file_desc);
|
||||
|
||||
UINT32 attributes;
|
||||
UINT32 attributes{};
|
||||
DECODE_OR_RETURN(request, attributes);
|
||||
|
||||
UINT64 creation_time;
|
||||
UINT64 creation_time{};
|
||||
DECODE_OR_RETURN(request, creation_time);
|
||||
|
||||
UINT64 last_access_time;
|
||||
UINT64 last_access_time{};
|
||||
DECODE_OR_RETURN(request, last_access_time);
|
||||
|
||||
UINT64 last_write_time;
|
||||
UINT64 last_write_time{};
|
||||
DECODE_OR_RETURN(request, last_write_time);
|
||||
|
||||
UINT64 change_time;
|
||||
UINT64 change_time{};
|
||||
DECODE_OR_RETURN(request, change_time);
|
||||
|
||||
remote::file_info file_info{};
|
||||
@ -429,13 +439,13 @@ public:
|
||||
packet &response) -> packet::error_type {
|
||||
auto ret = STATUS_SUCCESS;
|
||||
|
||||
HANDLE file_desc;
|
||||
HANDLE file_desc{};
|
||||
DECODE_OR_RETURN(request, file_desc);
|
||||
|
||||
UINT64 new_size;
|
||||
UINT64 new_size{};
|
||||
DECODE_OR_RETURN(request, new_size);
|
||||
|
||||
BOOLEAN set_allocation_size;
|
||||
BOOLEAN set_allocation_size{};
|
||||
DECODE_OR_RETURN(request, set_allocation_size);
|
||||
|
||||
remote::file_info file_info{};
|
||||
@ -456,8 +466,7 @@ public:
|
||||
std::wstring location;
|
||||
DECODE_OR_RETURN(request, location);
|
||||
|
||||
ret = this->winfsp_unmounted(location);
|
||||
return ret;
|
||||
return this->winfsp_unmounted(location);
|
||||
}});
|
||||
handler_lookup_.insert(
|
||||
{"::winfsp_write",
|
||||
@ -466,19 +475,19 @@ public:
|
||||
packet &response) -> packet::error_type {
|
||||
auto ret = STATUS_SUCCESS;
|
||||
|
||||
HANDLE file_desc;
|
||||
HANDLE file_desc{};
|
||||
DECODE_OR_RETURN(request, file_desc);
|
||||
|
||||
UINT32 length;
|
||||
UINT32 length{};
|
||||
DECODE_OR_RETURN(request, length);
|
||||
|
||||
UINT64 offset;
|
||||
UINT64 offset{};
|
||||
DECODE_OR_RETURN(request, offset);
|
||||
|
||||
BOOLEAN write_to_end;
|
||||
BOOLEAN write_to_end{};
|
||||
DECODE_OR_RETURN(request, write_to_end);
|
||||
|
||||
BOOLEAN constrained_io;
|
||||
BOOLEAN constrained_io{};
|
||||
DECODE_OR_RETURN(request, constrained_io);
|
||||
|
||||
auto *buffer = request->current_pointer();
|
||||
@ -504,10 +513,10 @@ public:
|
||||
std::string path;
|
||||
DECODE_OR_RETURN(request, path);
|
||||
|
||||
std::int32_t mask;
|
||||
std::int32_t mask{};
|
||||
DECODE_OR_RETURN(request, mask);
|
||||
|
||||
return this->fuse_access(&path[0], mask);
|
||||
return this->fuse_access(path.data(), mask);
|
||||
}});
|
||||
handler_lookup_.insert(
|
||||
{"::fuse_chflags",
|
||||
@ -519,10 +528,10 @@ public:
|
||||
std::string path;
|
||||
DECODE_OR_RETURN(request, path);
|
||||
|
||||
std::uint32_t flags;
|
||||
std::uint32_t flags{};
|
||||
DECODE_OR_RETURN(request, flags);
|
||||
|
||||
return this->fuse_chflags(&path[0], flags);
|
||||
return this->fuse_chflags(path.data(), flags);
|
||||
}});
|
||||
handler_lookup_.insert(
|
||||
{"::fuse_chmod",
|
||||
@ -549,10 +558,10 @@ public:
|
||||
std::string path;
|
||||
DECODE_OR_RETURN(request, path);
|
||||
|
||||
remote::user_id uid;
|
||||
remote::user_id uid{};
|
||||
DECODE_OR_RETURN(request, uid);
|
||||
|
||||
remote::group_id gid;
|
||||
remote::group_id gid{};
|
||||
DECODE_OR_RETURN(request, gid);
|
||||
|
||||
return this->fuse_chown(&path[0], uid, gid);
|
||||
@ -567,18 +576,19 @@ public:
|
||||
std::string path;
|
||||
DECODE_OR_RETURN(request, path);
|
||||
|
||||
remote::file_mode mode;
|
||||
remote::file_mode mode{};
|
||||
DECODE_OR_RETURN(request, mode);
|
||||
|
||||
remote::open_flags flags;
|
||||
remote::open_flags flags{};
|
||||
DECODE_OR_RETURN(request, flags);
|
||||
|
||||
remote::file_handle handle;
|
||||
if ((ret = this->fuse_create(&path[0], mode, flags, handle)) >= 0) {
|
||||
remote::file_handle handle{};
|
||||
if ((ret = this->fuse_create(path.data(), mode, flags, handle)) >=
|
||||
0) {
|
||||
#ifdef _WIN32
|
||||
this->set_compat_client_id(handle, client_id);
|
||||
#else
|
||||
this->set_client_id(handle, client_id);
|
||||
this->set_client_id(static_cast<native_handle>(handle), client_id);
|
||||
#endif
|
||||
response.encode(handle);
|
||||
}
|
||||
@ -623,18 +633,18 @@ public:
|
||||
std::string path;
|
||||
DECODE_OR_RETURN(request, path);
|
||||
|
||||
remote::file_handle handle;
|
||||
remote::file_handle handle{};
|
||||
DECODE_OR_RETURN(request, handle);
|
||||
|
||||
remote::user_id uid;
|
||||
remote::user_id uid{};
|
||||
DECODE_OR_RETURN(request, uid);
|
||||
|
||||
remote::group_id gid;
|
||||
remote::group_id gid{};
|
||||
DECODE_OR_RETURN(request, gid);
|
||||
|
||||
remote::stat st{};
|
||||
bool directory = false;
|
||||
ret = this->fuse_fgetattr(&path[0], st, directory, handle);
|
||||
ret = this->fuse_fgetattr(path.data(), st, directory, handle);
|
||||
if (ret == 0) {
|
||||
st.st_uid = uid;
|
||||
st.st_gid = gid;
|
||||
@ -657,10 +667,10 @@ public:
|
||||
remote::setattr_x attr{};
|
||||
DECODE_OR_RETURN(request, attr);
|
||||
|
||||
remote::file_handle handle;
|
||||
remote::file_handle handle{};
|
||||
DECODE_OR_RETURN(request, handle);
|
||||
|
||||
return this->fuse_fsetattr_x(&path[0], attr, handle);
|
||||
return this->fuse_fsetattr_x(path.data(), attr, handle);
|
||||
}});
|
||||
handler_lookup_.insert(
|
||||
{"::fuse_fsync",
|
||||
@ -833,7 +843,7 @@ public:
|
||||
#ifdef _WIN32
|
||||
this->set_compat_client_id(handle, client_id);
|
||||
#else
|
||||
this->set_client_id(handle, client_id);
|
||||
this->set_client_id(static_cast<native_handle>(handle), client_id);
|
||||
#endif
|
||||
response.encode(handle);
|
||||
}
|
||||
@ -965,7 +975,7 @@ public:
|
||||
[this](std::uint32_t, const std::string &, std::uint64_t,
|
||||
const std::string &, packet *request,
|
||||
packet &) -> packet::error_type {
|
||||
auto ret = 0;
|
||||
std::int32_t ret{0};
|
||||
|
||||
std::string from;
|
||||
DECODE_OR_RETURN(request, from);
|
||||
@ -973,26 +983,26 @@ public:
|
||||
std::string to;
|
||||
DECODE_OR_RETURN(request, to);
|
||||
|
||||
return this->fuse_rename(&from[0], &to[0]);
|
||||
return this->fuse_rename(from.data(), to.data());
|
||||
}});
|
||||
handler_lookup_.insert(
|
||||
{"::fuse_rmdir",
|
||||
[this](std::uint32_t, const std::string &, std::uint64_t,
|
||||
const std::string &, packet *request,
|
||||
packet &) -> packet::error_type {
|
||||
auto ret = 0;
|
||||
std::int32_t ret{0};
|
||||
|
||||
std::string path;
|
||||
DECODE_OR_RETURN(request, path);
|
||||
|
||||
return this->fuse_rmdir(&path[0]);
|
||||
return this->fuse_rmdir(path.data());
|
||||
}});
|
||||
handler_lookup_.insert(
|
||||
{"::fuse_setattr_x",
|
||||
[this](std::uint32_t, const std::string &, std::uint64_t,
|
||||
const std::string &, packet *request,
|
||||
packet &) -> packet::error_type {
|
||||
auto ret = 0;
|
||||
std::int32_t ret{0};
|
||||
|
||||
std::string path;
|
||||
DECODE_OR_RETURN(request, path);
|
||||
@ -1000,64 +1010,64 @@ public:
|
||||
remote::setattr_x attr{};
|
||||
DECODE_OR_RETURN(request, attr);
|
||||
|
||||
return this->fuse_setattr_x(&path[0], attr);
|
||||
return this->fuse_setattr_x(path.data(), attr);
|
||||
}});
|
||||
handler_lookup_.insert(
|
||||
{"::fuse_setbkuptime",
|
||||
[this](std::uint32_t, const std::string &, std::uint64_t,
|
||||
const std::string &, packet *request,
|
||||
packet &) -> packet::error_type {
|
||||
auto ret = 0;
|
||||
std::int32_t ret{0};
|
||||
|
||||
std::string path;
|
||||
DECODE_OR_RETURN(request, path);
|
||||
|
||||
remote::file_time bkuptime;
|
||||
remote::file_time bkuptime{};
|
||||
DECODE_OR_RETURN(request, bkuptime);
|
||||
|
||||
return this->fuse_setbkuptime(&path[0], bkuptime);
|
||||
return this->fuse_setbkuptime(path.data(), bkuptime);
|
||||
}});
|
||||
handler_lookup_.insert(
|
||||
{"::fuse_setchgtime",
|
||||
[this](std::uint32_t, const std::string &, std::uint64_t,
|
||||
const std::string &, packet *request,
|
||||
packet &) -> packet::error_type {
|
||||
auto ret = 0;
|
||||
std::int32_t ret{0};
|
||||
|
||||
std::string path;
|
||||
DECODE_OR_RETURN(request, path);
|
||||
|
||||
remote::file_time chgtime;
|
||||
remote::file_time chgtime{};
|
||||
DECODE_OR_RETURN(request, chgtime);
|
||||
|
||||
return this->fuse_setchgtime(&path[0], chgtime);
|
||||
return this->fuse_setchgtime(path.data(), chgtime);
|
||||
}});
|
||||
handler_lookup_.insert(
|
||||
{"::fuse_setcrtime",
|
||||
[this](std::uint32_t, const std::string &, std::uint64_t,
|
||||
const std::string &, packet *request,
|
||||
packet &) -> packet::error_type {
|
||||
auto ret = 0;
|
||||
std::int32_t ret{0};
|
||||
|
||||
std::string path;
|
||||
DECODE_OR_RETURN(request, path);
|
||||
|
||||
remote::file_time crtime;
|
||||
remote::file_time crtime{};
|
||||
DECODE_OR_RETURN(request, crtime);
|
||||
|
||||
return this->fuse_setcrtime(&path[0], crtime);
|
||||
return this->fuse_setcrtime(path.data(), crtime);
|
||||
}});
|
||||
handler_lookup_.insert(
|
||||
{"::fuse_setvolname",
|
||||
[this](std::uint32_t, const std::string &, std::uint64_t,
|
||||
const std::string &, packet *request,
|
||||
packet &) -> packet::error_type {
|
||||
auto ret = 0;
|
||||
std::int32_t ret{0};
|
||||
|
||||
std::string name;
|
||||
DECODE_OR_RETURN(request, name);
|
||||
|
||||
return this->fuse_setvolname(&name[0]);
|
||||
return this->fuse_setvolname(name.data());
|
||||
}});
|
||||
/*handlerLookup_.insert({"::fuse_setxattr",
|
||||
[this](std::uint32_t serviceFlags, const std::string
|
||||
@ -1125,16 +1135,16 @@ public:
|
||||
[this](std::uint32_t, const std::string &, std::uint64_t,
|
||||
const std::string &, packet *request,
|
||||
packet &response) -> packet::error_type {
|
||||
auto ret = -1;
|
||||
std::int32_t ret{-1};
|
||||
|
||||
std::string path;
|
||||
DECODE_OR_RETURN(request, path);
|
||||
|
||||
std::uint64_t frsize;
|
||||
std::uint64_t frsize{};
|
||||
DECODE_OR_RETURN(request, frsize);
|
||||
|
||||
remote::statfs st{};
|
||||
ret = this->fuse_statfs(&path[0], frsize, st);
|
||||
ret = this->fuse_statfs(path.data(), frsize, st);
|
||||
if (ret == 0) {
|
||||
response.encode(st);
|
||||
}
|
||||
@ -1145,16 +1155,16 @@ public:
|
||||
[this](std::uint32_t, const std::string &, std::uint64_t,
|
||||
const std::string &, packet *request,
|
||||
packet &response) -> packet::error_type {
|
||||
auto ret = -1;
|
||||
std::int32_t ret{-1};
|
||||
|
||||
std::string path;
|
||||
DECODE_OR_RETURN(request, path);
|
||||
|
||||
std::uint64_t bsize;
|
||||
std::uint64_t bsize{};
|
||||
DECODE_OR_RETURN(request, bsize);
|
||||
|
||||
remote::statfs_x st{};
|
||||
ret = this->fuse_statfs_x(&path[0], bsize, st);
|
||||
ret = this->fuse_statfs_x(path.data(), bsize, st);
|
||||
if (ret == 0) {
|
||||
response.encode(st);
|
||||
}
|
||||
@ -1165,34 +1175,34 @@ public:
|
||||
[this](std::uint32_t, const std::string &, std::uint64_t,
|
||||
const std::string &, packet *request,
|
||||
packet &) -> packet::error_type {
|
||||
auto ret = 0;
|
||||
std::int32_t ret{};
|
||||
|
||||
std::string path;
|
||||
DECODE_OR_RETURN(request, path);
|
||||
|
||||
remote::file_offset size;
|
||||
remote::file_offset size{};
|
||||
DECODE_OR_IGNORE(request, size);
|
||||
|
||||
return this->fuse_truncate(&path[0], size);
|
||||
return this->fuse_truncate(path.data(), size);
|
||||
}});
|
||||
handler_lookup_.insert(
|
||||
{"::fuse_unlink",
|
||||
[this](std::uint32_t, const std::string &, std::uint64_t,
|
||||
const std::string &, packet *request,
|
||||
packet &) -> packet::error_type {
|
||||
auto ret = 0;
|
||||
std::int32_t ret{};
|
||||
|
||||
std::string path;
|
||||
DECODE_OR_RETURN(request, path);
|
||||
|
||||
return this->fuse_unlink(&path[0]);
|
||||
return this->fuse_unlink(path.data());
|
||||
}});
|
||||
handler_lookup_.insert(
|
||||
{"::fuse_utimens",
|
||||
[this](std::uint32_t, const std::string &, std::uint64_t,
|
||||
const std::string &, packet *request,
|
||||
packet &) -> packet::error_type {
|
||||
auto ret = 0;
|
||||
std::int32_t ret{};
|
||||
|
||||
std::string path;
|
||||
DECODE_OR_RETURN(request, path);
|
||||
@ -1200,13 +1210,13 @@ public:
|
||||
remote::file_time tv[2] = {0};
|
||||
if ((ret = request->decode(&tv[0], sizeof(remote::file_time) * 2)) ==
|
||||
0) {
|
||||
std::uint64_t op0;
|
||||
std::uint64_t op0{};
|
||||
DECODE_OR_RETURN(request, op0);
|
||||
|
||||
std::uint64_t op1;
|
||||
std::uint64_t op1{};
|
||||
DECODE_OR_RETURN(request, op1);
|
||||
|
||||
ret = this->fuse_utimens(&path[0], tv, op0, op1);
|
||||
ret = this->fuse_utimens(path.data(), tv, op0, op1);
|
||||
}
|
||||
return ret;
|
||||
}});
|
||||
@ -1215,27 +1225,27 @@ public:
|
||||
[this](std::uint32_t, const std::string &, std::uint64_t,
|
||||
const std::string &, packet *request,
|
||||
packet &) -> packet::error_type {
|
||||
std::int32_t ret = 0;
|
||||
std::int32_t ret{};
|
||||
|
||||
std::string path;
|
||||
DECODE_OR_RETURN(request, path);
|
||||
|
||||
remote::file_size writeSize;
|
||||
DECODE_OR_RETURN(request, writeSize);
|
||||
remote::file_size write_size{};
|
||||
DECODE_OR_RETURN(request, write_size);
|
||||
|
||||
if (writeSize > std::numeric_limits<std::size_t>::max()) {
|
||||
if (write_size > std::numeric_limits<std::size_t>::max()) {
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
data_buffer buffer(static_cast<std::size_t>(writeSize));
|
||||
if ((ret = request->decode(&buffer[0], buffer.size())) == 0) {
|
||||
remote::file_offset write_offset;
|
||||
data_buffer buffer(static_cast<std::size_t>(write_size));
|
||||
if ((ret = request->decode(buffer.data(), buffer.size())) == 0) {
|
||||
remote::file_offset write_offset{};
|
||||
DECODE_OR_RETURN(request, write_offset);
|
||||
|
||||
remote::file_handle handle;
|
||||
remote::file_handle handle{};
|
||||
DECODE_OR_RETURN(request, handle);
|
||||
|
||||
ret = this->fuse_write(&path[0], &buffer[0], writeSize,
|
||||
ret = this->fuse_write(path.data(), buffer.data(), write_size,
|
||||
write_offset, handle);
|
||||
}
|
||||
return ret;
|
||||
@ -1245,12 +1255,12 @@ public:
|
||||
[this](std::uint32_t, const std::string &, std::uint64_t,
|
||||
const std::string &, packet *request,
|
||||
packet &) -> packet::error_type {
|
||||
std::int32_t ret = 0;
|
||||
std::int32_t ret{};
|
||||
|
||||
std::string path;
|
||||
DECODE_OR_RETURN(request, path);
|
||||
|
||||
remote::file_size write_size;
|
||||
remote::file_size write_size{};
|
||||
DECODE_OR_RETURN(request, write_size);
|
||||
|
||||
if (write_size > std::numeric_limits<std::size_t>::max()) {
|
||||
@ -1258,18 +1268,18 @@ public:
|
||||
}
|
||||
|
||||
data_buffer buffer(static_cast<std::size_t>(write_size));
|
||||
if ((ret = request->decode(&buffer[0], buffer.size())) == 0) {
|
||||
if ((ret = request->decode(buffer.data(), buffer.size())) == 0) {
|
||||
buffer = macaron::Base64::Decode(
|
||||
std::string(buffer.begin(), buffer.end()));
|
||||
write_size = buffer.size();
|
||||
|
||||
remote::file_offset write_offset;
|
||||
remote::file_offset write_offset{};
|
||||
DECODE_OR_RETURN(request, write_offset);
|
||||
|
||||
remote::file_handle handle;
|
||||
remote::file_handle handle{};
|
||||
DECODE_OR_RETURN(request, handle);
|
||||
|
||||
ret = this->fuse_write(&path[0], &buffer[0], write_size,
|
||||
ret = this->fuse_write(path.data(), buffer.data(), write_size,
|
||||
write_offset, handle);
|
||||
}
|
||||
return ret;
|
||||
@ -1279,7 +1289,7 @@ public:
|
||||
[this](std::uint32_t, const std::string &client_id, std::uint64_t,
|
||||
const std::string &, packet *request,
|
||||
packet &response) -> packet::error_type {
|
||||
std::int32_t ret = 0;
|
||||
std::int32_t ret{};
|
||||
|
||||
std::string path;
|
||||
DECODE_OR_RETURN(request, path);
|
||||
@ -1288,7 +1298,7 @@ public:
|
||||
json_data["handle"] = -1;
|
||||
json_data["page_count"] = 0;
|
||||
json_data["path"] = path;
|
||||
if ((ret = this->json_create_directory_snapshot(&path[0],
|
||||
if ((ret = this->json_create_directory_snapshot(path.data(),
|
||||
json_data)) == 0) {
|
||||
this->add_directory(client_id,
|
||||
reinterpret_cast<void *>(
|
||||
@ -1307,10 +1317,10 @@ public:
|
||||
std::string path;
|
||||
DECODE_OR_RETURN(request, path);
|
||||
|
||||
remote::file_handle handle;
|
||||
remote::file_handle handle{};
|
||||
DECODE_OR_RETURN(request, handle);
|
||||
|
||||
std::uint32_t page;
|
||||
std::uint32_t page{};
|
||||
DECODE_OR_RETURN(request, page);
|
||||
|
||||
ret = -EBADF;
|
||||
@ -1338,10 +1348,10 @@ public:
|
||||
std::string path;
|
||||
DECODE_OR_RETURN(request, path);
|
||||
|
||||
remote::file_handle handle;
|
||||
remote::file_handle handle{};
|
||||
DECODE_OR_RETURN(request, handle);
|
||||
|
||||
ret = this->json_release_directory_snapshot(&path[0], handle);
|
||||
ret = this->json_release_directory_snapshot(path.data(), handle);
|
||||
if (this->remove_directory(client_id,
|
||||
reinterpret_cast<void *>(handle))) {
|
||||
return ret;
|
||||
@ -1380,7 +1390,7 @@ public:
|
||||
protected:
|
||||
app_config &config_;
|
||||
drive &drive_;
|
||||
const std::string mount_location_;
|
||||
std::string mount_location_;
|
||||
|
||||
private:
|
||||
client_pool client_pool_;
|
||||
@ -1422,7 +1432,7 @@ protected:
|
||||
}
|
||||
|
||||
void delete_open_directory(void *dir) override {
|
||||
if (dir) {
|
||||
if (dir != nullptr) {
|
||||
delete reinterpret_cast<directory_iterator *>(dir);
|
||||
}
|
||||
}
|
||||
|
@ -29,84 +29,84 @@ class i_remote_instance : public virtual i_remote_json {
|
||||
INTERFACE_SETUP(i_remote_instance);
|
||||
|
||||
public:
|
||||
virtual auto winfsp_can_delete(PVOID fileDesc, PWSTR fileName)
|
||||
virtual auto winfsp_can_delete(PVOID file_desc, PWSTR file_name)
|
||||
-> packet::error_type = 0;
|
||||
|
||||
virtual auto winfsp_cleanup(PVOID fileDesc, PWSTR fileName, UINT32 flags,
|
||||
BOOLEAN &wasClosed) -> packet::error_type = 0;
|
||||
virtual auto winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags,
|
||||
BOOLEAN &was_closed) -> packet::error_type = 0;
|
||||
|
||||
virtual auto winfsp_close(PVOID fileDesc) -> packet::error_type = 0;
|
||||
virtual auto winfsp_close(PVOID file_desc) -> packet::error_type = 0;
|
||||
|
||||
virtual auto winfsp_create(PWSTR fileName, UINT32 createOptions,
|
||||
UINT32 grantedAccess, UINT32 fileAttributes,
|
||||
UINT64 allocationSize, PVOID *fileDesc,
|
||||
remote::file_info *fileInfo,
|
||||
std::string &normalizedName, BOOLEAN &exists)
|
||||
virtual auto winfsp_create(PWSTR file_name, UINT32 create_options,
|
||||
UINT32 granted_access, UINT32 file_attributes,
|
||||
UINT64 allocation_size, PVOID *file_desc,
|
||||
remote::file_info *file_info,
|
||||
std::string &normalized_name, BOOLEAN &exists)
|
||||
-> packet::error_type = 0;
|
||||
|
||||
virtual auto winfsp_flush(PVOID fileDesc, remote::file_info *fileInfo)
|
||||
virtual auto winfsp_flush(PVOID file_desc, remote::file_info *file_info)
|
||||
-> packet::error_type = 0;
|
||||
|
||||
virtual auto winfsp_get_dir_buffer(PVOID fileDesc, PVOID *&ptr)
|
||||
virtual auto winfsp_get_dir_buffer(PVOID file_desc, PVOID *&ptr)
|
||||
-> packet::error_type = 0;
|
||||
|
||||
virtual auto winfsp_get_file_info(PVOID fileDesc, remote::file_info *fileInfo)
|
||||
virtual auto winfsp_get_file_info(PVOID file_desc, remote::file_info *file_info)
|
||||
-> packet::error_type = 0;
|
||||
|
||||
virtual auto
|
||||
winfsp_get_security_by_name(PWSTR fileName, PUINT32 fileAttributes,
|
||||
std::uint64_t *securityDescriptorSize,
|
||||
std::wstring &strDescriptor)
|
||||
winfsp_get_security_by_name(PWSTR file_name, PUINT32 file_attributes,
|
||||
std::uint64_t *security_descriptor_size,
|
||||
std::wstring &str_descriptor)
|
||||
-> packet::error_type = 0;
|
||||
|
||||
virtual auto winfsp_get_volume_info(UINT64 &totalSize, UINT64 &freeSize,
|
||||
std::string &volumeLabel)
|
||||
virtual auto winfsp_get_volume_info(UINT64 &total_size, UINT64 &free_size,
|
||||
std::string &volume_label)
|
||||
-> packet::error_type = 0;
|
||||
|
||||
virtual auto winfsp_mounted(const std::wstring &location)
|
||||
-> packet::error_type = 0;
|
||||
|
||||
virtual auto winfsp_open(PWSTR fileName, UINT32 createOptions,
|
||||
UINT32 grantedAccess, PVOID *fileDesc,
|
||||
remote::file_info *fileInfo,
|
||||
std::string &normalizedName)
|
||||
virtual auto winfsp_open(PWSTR file_name, UINT32 create_options,
|
||||
UINT32 granted_access, PVOID *file_desc,
|
||||
remote::file_info *file_info,
|
||||
std::string &normalized_name)
|
||||
-> packet::error_type = 0;
|
||||
|
||||
virtual auto winfsp_overwrite(PVOID fileDesc, UINT32 fileAttributes,
|
||||
BOOLEAN replaceFileAttributes,
|
||||
UINT64 allocationSize,
|
||||
remote::file_info *fileInfo)
|
||||
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 fileDesc, PVOID buffer, UINT64 offset,
|
||||
UINT32 length, PUINT32 bytesTransferred)
|
||||
virtual auto winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||
UINT32 length, PUINT32 bytes_transferred)
|
||||
-> packet::error_type = 0;
|
||||
|
||||
virtual auto winfsp_read_directory(PVOID fileDesc, PWSTR pattern,
|
||||
virtual auto winfsp_read_directory(PVOID file_desc, PWSTR pattern,
|
||||
PWSTR marker, json &itemList)
|
||||
-> packet::error_type = 0;
|
||||
|
||||
virtual auto winfsp_rename(PVOID fileDesc, PWSTR fileName, PWSTR newFileName,
|
||||
BOOLEAN replaceIfExists) -> packet::error_type = 0;
|
||||
virtual auto winfsp_rename(PVOID file_desc, PWSTR file_name, PWSTR new_file_name,
|
||||
BOOLEAN replace_if_exists) -> packet::error_type = 0;
|
||||
|
||||
virtual auto winfsp_set_basic_info(PVOID fileDesc, UINT32 fileAttributes,
|
||||
UINT64 creationTime, UINT64 lastAccessTime,
|
||||
UINT64 lastWriteTime, UINT64 changeTime,
|
||||
remote::file_info *fileInfo)
|
||||
virtual auto winfsp_set_basic_info(PVOID file_desc, UINT32 file_attributes,
|
||||
UINT64 creation_time, UINT64 last_access_time,
|
||||
UINT64 last_write_time, UINT64 change_time,
|
||||
remote::file_info *file_info)
|
||||
-> packet::error_type = 0;
|
||||
|
||||
virtual auto winfsp_set_file_size(PVOID fileDesc, UINT64 newSize,
|
||||
BOOLEAN setAllocationSize,
|
||||
remote::file_info *fileInfo)
|
||||
virtual auto winfsp_set_file_size(PVOID file_desc, UINT64 new_size,
|
||||
BOOLEAN set_allocation_size,
|
||||
remote::file_info *file_info)
|
||||
-> packet::error_type = 0;
|
||||
|
||||
virtual auto winfsp_unmounted(const std::wstring &location)
|
||||
-> packet::error_type = 0;
|
||||
|
||||
virtual auto winfsp_write(PVOID fileDesc, PVOID buffer, UINT64 offset,
|
||||
UINT32 length, BOOLEAN writeToEndOfFile,
|
||||
BOOLEAN constrainedIo, PUINT32 bytesTransferred,
|
||||
remote::file_info *fileInfo)
|
||||
virtual auto winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||
UINT32 length, BOOLEAN write_to_end,
|
||||
BOOLEAN constrained_io, PUINT32 bytes_transferred,
|
||||
remote::file_info *file_info)
|
||||
-> packet::error_type = 0;
|
||||
};
|
||||
|
||||
|
@ -266,7 +266,7 @@ public:
|
||||
remote::file_info *file_info)
|
||||
-> packet::error_type override;
|
||||
|
||||
auto winfsp_set_file_size(PVOID file_desc, UINT64 newSize,
|
||||
auto winfsp_set_file_size(PVOID file_desc, UINT64 new_size,
|
||||
BOOLEAN set_allocation_size,
|
||||
remote::file_info *file_info)
|
||||
-> packet::error_type override;
|
||||
|
@ -172,7 +172,7 @@ public:
|
||||
PULONG bytes_transferred) -> NTSTATUS override;
|
||||
|
||||
auto Rename(PVOID file_node, PVOID file_desc, PWSTR file_name,
|
||||
PWSTR newFileName, BOOLEAN replace_if_exists)
|
||||
PWSTR new_file_name, BOOLEAN replace_if_exists)
|
||||
-> NTSTATUS override;
|
||||
|
||||
auto SetBasicInfo(PVOID file_node, PVOID file_desc, UINT32 attributes,
|
||||
|
@ -23,7 +23,13 @@
|
||||
#define INCLUDE_EVENTS_EVENT_HPP_
|
||||
|
||||
namespace repertory {
|
||||
enum class event_level { error, warn, normal, debug, verbose };
|
||||
enum class event_level {
|
||||
error,
|
||||
warn,
|
||||
normal,
|
||||
debug,
|
||||
verbose,
|
||||
};
|
||||
|
||||
auto event_level_from_string(std::string level) -> event_level;
|
||||
|
||||
@ -37,10 +43,14 @@ protected:
|
||||
: allow_async_(allow_async), ss_(ss.str()), j_(std::move(j)) {}
|
||||
|
||||
public:
|
||||
event(const event &) = delete;
|
||||
event(event &&) = delete;
|
||||
auto operator=(const event &) -> event & = delete;
|
||||
auto operator=(event &&) -> event & = delete;
|
||||
virtual ~event() = default;
|
||||
|
||||
private:
|
||||
const bool allow_async_;
|
||||
bool allow_async_;
|
||||
|
||||
protected:
|
||||
std::stringstream ss_;
|
||||
|
@ -32,12 +32,12 @@ using event_consumer = event_system::event_consumer;
|
||||
|
||||
#define E_CAST(t) ((std::string)t)
|
||||
#define E_DOUBLE(d) std::to_string(d)
|
||||
#define E_DOUBLE_PRECISE(d) \
|
||||
#define E_DOUBLE_PRECISE(dbl_val) \
|
||||
([](const double &d) -> std::string { \
|
||||
std::stringstream ss; \
|
||||
ss << std::fixed << std::setprecision(2) << d; \
|
||||
return ss.str(); \
|
||||
})(d)
|
||||
})(dbl_val)
|
||||
#define E_FROM_BOOL(t) std::to_string(t)
|
||||
#define E_FROM_EXCEPTION(e) std::string(e.what() ? e.what() : "")
|
||||
#define E_FROM_INT32(t) std::to_string(t)
|
||||
@ -69,8 +69,9 @@ using event_consumer = event_system::event_consumer;
|
||||
#define E_PROP(type, name, short_name, ts) \
|
||||
private: \
|
||||
void init_##short_name(const type &val) { \
|
||||
ss_ << "|" << #short_name << "|" << ts(val); \
|
||||
j_[#name] = ts(val); \
|
||||
auto ts_val = ts(val); \
|
||||
ss_ << "|" << #short_name << "|" << ts_val; \
|
||||
j_[#name] = ts_val; \
|
||||
} \
|
||||
\
|
||||
public: \
|
||||
|
@ -54,6 +54,12 @@ public:
|
||||
|
||||
~event_consumer() { t_event_system::instance().release(this); }
|
||||
|
||||
public:
|
||||
event_consumer(const event_consumer &) = delete;
|
||||
event_consumer(event_consumer &&) = delete;
|
||||
auto operator=(const event_consumer &) -> event_consumer & = delete;
|
||||
auto operator=(event_consumer &&) -> event_consumer & = delete;
|
||||
|
||||
private:
|
||||
std::function<void(const event &)> callback_;
|
||||
|
||||
@ -82,9 +88,9 @@ private:
|
||||
void process_events() {
|
||||
std::vector<std::shared_ptr<event_type>> events;
|
||||
{
|
||||
unique_mutex_lock l(event_mutex_);
|
||||
unique_mutex_lock lock(event_mutex_);
|
||||
if (not stop_requested_ && event_list_.empty()) {
|
||||
event_notify_.wait_for(l, 1s);
|
||||
event_notify_.wait_for(lock, 1s);
|
||||
}
|
||||
|
||||
if (not event_list_.empty()) {
|
||||
@ -96,15 +102,16 @@ private:
|
||||
const auto notify_events = [this](const std::string &name,
|
||||
const event_type &event) {
|
||||
std::deque<std::future<void>> futures;
|
||||
recur_mutex_lock l(consumer_mutex_);
|
||||
recur_mutex_lock lock(consumer_mutex_);
|
||||
if (event_consumers_.find(name) != event_consumers_.end()) {
|
||||
for (auto *ec : event_consumers_[name]) {
|
||||
for (auto *consumer : event_consumers_[name]) {
|
||||
if (event.get_allow_async()) {
|
||||
futures.emplace_back(std::async(std::launch::async, [ec, &event]() {
|
||||
ec->notify_event(event);
|
||||
}));
|
||||
futures.emplace_back(
|
||||
std::async(std::launch::async, [consumer, &event]() {
|
||||
consumer->notify_event(event);
|
||||
}));
|
||||
} else {
|
||||
ec->notify_event(event);
|
||||
consumer->notify_event(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -115,48 +122,48 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
for (const auto &e : events) {
|
||||
notify_events("", *e.get());
|
||||
notify_events(e->get_name(), *e.get());
|
||||
for (const auto &evt : events) {
|
||||
notify_events("", *evt.get());
|
||||
notify_events(evt->get_name(), *evt.get());
|
||||
}
|
||||
}
|
||||
|
||||
void queue_event(event_type *e) {
|
||||
mutex_lock l(event_mutex_);
|
||||
event_list_.emplace_back(std::shared_ptr<event_type>(e));
|
||||
void queue_event(std::shared_ptr<event_type> evt) {
|
||||
mutex_lock lock(event_mutex_);
|
||||
event_list_.push_back(std::move(evt));
|
||||
event_notify_.notify_all();
|
||||
}
|
||||
|
||||
public:
|
||||
void attach(event_consumer *ec) {
|
||||
recur_mutex_lock l(consumer_mutex_);
|
||||
event_consumers_[""].push_back(ec);
|
||||
void attach(event_consumer *consumer) {
|
||||
recur_mutex_lock lock(consumer_mutex_);
|
||||
event_consumers_[""].push_back(consumer);
|
||||
}
|
||||
|
||||
void attach(const std::string &event_name, event_consumer *ec) {
|
||||
recur_mutex_lock l(consumer_mutex_);
|
||||
event_consumers_[event_name].push_back(ec);
|
||||
void attach(const std::string &event_name, event_consumer *consumer) {
|
||||
recur_mutex_lock lock(consumer_mutex_);
|
||||
event_consumers_[event_name].push_back(consumer);
|
||||
}
|
||||
|
||||
template <typename t, typename... args> void raise(args &&...a) {
|
||||
queue_event(new t(std::forward<args>(a)...));
|
||||
template <typename event_t, typename... arg_t> void raise(arg_t &&...args) {
|
||||
queue_event(std::make_shared<event_t>(std::forward<arg_t>(args)...));
|
||||
}
|
||||
|
||||
void release(event_consumer *ec) {
|
||||
recur_mutex_lock l(consumer_mutex_);
|
||||
auto it = std::find_if(event_consumers_.begin(), event_consumers_.end(),
|
||||
[&](const auto &kv) -> bool {
|
||||
return utils::collection_includes(kv.second, ec);
|
||||
});
|
||||
void release(event_consumer *consumer) {
|
||||
recur_mutex_lock lock(consumer_mutex_);
|
||||
auto iter =
|
||||
std::find_if(event_consumers_.begin(), event_consumers_.end(),
|
||||
[&](const auto &item) -> bool {
|
||||
return utils::collection_includes(item.second, consumer);
|
||||
});
|
||||
|
||||
if (it != event_consumers_.end()) {
|
||||
auto &q = (*it).second;
|
||||
utils::remove_element_from(q, ec);
|
||||
if (iter != event_consumers_.end()) {
|
||||
utils::remove_element_from((*iter).second, consumer);
|
||||
}
|
||||
}
|
||||
|
||||
void start() {
|
||||
mutex_lock l(run_mutex_);
|
||||
mutex_lock lock(run_mutex_);
|
||||
if (not event_thread_) {
|
||||
stop_requested_ = false;
|
||||
event_thread_ = std::make_unique<std::thread>([this]() {
|
||||
@ -168,7 +175,7 @@ public:
|
||||
}
|
||||
|
||||
void stop() {
|
||||
mutex_lock l(run_mutex_);
|
||||
mutex_lock lock(run_mutex_);
|
||||
if (event_thread_) {
|
||||
stop_requested_ = true;
|
||||
event_notify_.notify_all();
|
||||
|
@ -72,13 +72,13 @@ public:
|
||||
auto operator=(const download &) noexcept -> download & = delete;
|
||||
|
||||
private:
|
||||
bool complete_ = false;
|
||||
api_error error_ = api_error::success;
|
||||
bool complete_{false};
|
||||
api_error error_{api_error::success};
|
||||
std::mutex mtx_;
|
||||
std::condition_variable notify_;
|
||||
|
||||
public:
|
||||
void notify(const api_error &e);
|
||||
void notify(const api_error &err);
|
||||
|
||||
auto wait() -> api_error;
|
||||
};
|
||||
@ -194,17 +194,17 @@ public:
|
||||
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 &um);
|
||||
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 &um);
|
||||
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 &um);
|
||||
i_upload_manager &mgr);
|
||||
|
||||
private:
|
||||
open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||
@ -212,7 +212,7 @@ public:
|
||||
std::map<std::uint64_t, open_file_data> open_data,
|
||||
i_provider &provider,
|
||||
std::optional<boost::dynamic_bitset<>> read_state,
|
||||
i_upload_manager &um);
|
||||
i_upload_manager &mgr);
|
||||
|
||||
public:
|
||||
open_file() = delete;
|
||||
@ -225,11 +225,11 @@ public:
|
||||
~open_file() override;
|
||||
|
||||
private:
|
||||
i_upload_manager &um_;
|
||||
i_upload_manager &mgr_;
|
||||
|
||||
private:
|
||||
bool notified_ = false;
|
||||
std::size_t read_chunk_index_ = 0u;
|
||||
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_;
|
||||
@ -262,11 +262,13 @@ public:
|
||||
|
||||
auto is_write_supported() const -> bool override { return true; }
|
||||
|
||||
[[nodiscard]] auto native_operation(const native_operation_callback &cb)
|
||||
[[nodiscard]] auto
|
||||
native_operation(const native_operation_callback &callback)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto native_operation(std::uint64_t new_file_size,
|
||||
const native_operation_callback &cb)
|
||||
[[nodiscard]] auto
|
||||
native_operation(std::uint64_t new_file_size,
|
||||
const native_operation_callback &callback)
|
||||
-> api_error override;
|
||||
|
||||
void remove(std::uint64_t handle) override;
|
||||
@ -313,8 +315,8 @@ public:
|
||||
std::unique_ptr<std::thread> chunk_reverse_thread_;
|
||||
std::condition_variable chunk_notify_;
|
||||
mutable std::mutex chunk_mtx_;
|
||||
std::size_t current_chunk_ = 0u;
|
||||
std::size_t first_chunk_ = 0u;
|
||||
std::size_t current_chunk_{};
|
||||
std::size_t first_chunk_{};
|
||||
std::size_t last_chunk_;
|
||||
|
||||
private:
|
||||
@ -355,7 +357,8 @@ public:
|
||||
|
||||
auto is_write_supported() const -> bool override { return false; }
|
||||
|
||||
[[nodiscard]] auto native_operation(const native_operation_callback &cb)
|
||||
[[nodiscard]] auto
|
||||
native_operation(const native_operation_callback &callback)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto native_operation(std::uint64_t,
|
||||
|
@ -56,11 +56,11 @@ public:
|
||||
[[nodiscard]] virtual auto is_directory() const -> bool = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
native_operation(const native_operation_callback &cb) -> api_error = 0;
|
||||
native_operation(const native_operation_callback &callback) -> api_error = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
native_operation(std::uint64_t new_file_size,
|
||||
const native_operation_callback &cb) -> api_error = 0;
|
||||
const native_operation_callback &callback) -> api_error = 0;
|
||||
|
||||
[[nodiscard]] virtual auto read(std::size_t read_size,
|
||||
std::uint64_t read_offset, data_buffer &data)
|
||||
|
@ -68,11 +68,10 @@ public:
|
||||
[[nodiscard]] auto create_meta_attributes(
|
||||
std::uint64_t accessed_date, std::uint32_t attributes,
|
||||
std::uint64_t changed_date, std::uint64_t creation_date, bool directory,
|
||||
const std::string &encryption_token, std::uint32_t gid,
|
||||
const std::string &key, std::uint32_t mode, std::uint64_t modified_date,
|
||||
std::uint32_t osx_backup, std::uint32_t osx_flags, std::uint64_t size,
|
||||
const std::string &source_path, std::uint32_t uid,
|
||||
std::uint64_t written_date) -> api_meta_map;
|
||||
std::uint32_t gid, const std::string &key, std::uint32_t mode,
|
||||
std::uint64_t modified_date, std::uint32_t osx_backup,
|
||||
std::uint32_t osx_flags, std::uint64_t size, const std::string &source_path,
|
||||
std::uint32_t uid, std::uint64_t written_date) -> api_meta_map;
|
||||
|
||||
[[nodiscard]] auto provider_meta_handler(i_provider &provider, bool directory,
|
||||
const api_file &file) -> api_error;
|
||||
|
@ -73,11 +73,10 @@ public:
|
||||
[[nodiscard]] auto create_meta_attributes(
|
||||
std::uint64_t accessed_date, std::uint32_t attributes,
|
||||
std::uint64_t changed_date, std::uint64_t creation_date, bool directory,
|
||||
const std::string &encryption_token, std::uint32_t gid,
|
||||
const std::string &key, std::uint32_t mode, std::uint64_t modified_date,
|
||||
std::uint32_t osx_backup, std::uint32_t osx_flags, std::uint64_t size,
|
||||
const std::string &source_path, std::uint32_t uid,
|
||||
std::uint64_t written_date) -> api_meta_map;
|
||||
std::uint32_t gid, const std::string &key, std::uint32_t mode,
|
||||
std::uint64_t modified_date, std::uint32_t osx_backup,
|
||||
std::uint32_t osx_flags, std::uint64_t size, const std::string &source_path,
|
||||
std::uint32_t uid, std::uint64_t written_date) -> api_meta_map;
|
||||
|
||||
[[nodiscard]] auto provider_meta_handler(i_provider &provider, bool directory,
|
||||
const api_file &file) -> api_error;
|
||||
|
@ -22,127 +22,82 @@
|
||||
#ifndef INCLUDE_PROVIDERS_BASE_PROVIDER_HPP_
|
||||
#define INCLUDE_PROVIDERS_BASE_PROVIDER_HPP_
|
||||
|
||||
#include "db/meta_db.hpp"
|
||||
#include "providers/i_provider.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class app_config;
|
||||
class i_file_manager;
|
||||
class i_http_comm;
|
||||
|
||||
class base_provider : public i_provider {
|
||||
public:
|
||||
explicit base_provider(app_config &config);
|
||||
|
||||
~base_provider() override = default;
|
||||
base_provider(app_config &config, i_http_comm &comm)
|
||||
: config_(config), comm_(comm) {}
|
||||
|
||||
private:
|
||||
app_config &config_;
|
||||
std::atomic<std::uint64_t> used_space_{0U};
|
||||
i_http_comm &comm_;
|
||||
|
||||
protected:
|
||||
private:
|
||||
api_item_added_callback api_item_added_;
|
||||
std::unique_ptr<meta_db> meta_db_;
|
||||
mutable std::recursive_mutex notify_added_mutex_;
|
||||
i_file_manager *fm_ = nullptr;
|
||||
stop_type stop_requested_ = false;
|
||||
std::unique_ptr<rocksdb::DB> db_;
|
||||
std::string DB_NAME = "meta_db";
|
||||
i_file_manager *fm_{};
|
||||
|
||||
private:
|
||||
void remove_deleted_files();
|
||||
|
||||
protected:
|
||||
void calculate_used_drive_space(bool add_missing);
|
||||
[[nodiscard]] static auto create_api_file(std::string path, std::string key,
|
||||
std::uint64_t size) -> api_file;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
check_file_exists(const std::string &api_path) const -> api_error = 0;
|
||||
[[nodiscard]] static auto create_api_file(std::string path,
|
||||
std::uint64_t size,
|
||||
api_meta_map &meta) -> api_file;
|
||||
|
||||
void cleanup();
|
||||
[[nodiscard]] auto get_api_item_added() -> api_item_added_callback & {
|
||||
return api_item_added_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_api_item_added() const
|
||||
-> const api_item_added_callback & {
|
||||
return api_item_added_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_comm() const -> i_http_comm & { return comm_; }
|
||||
|
||||
[[nodiscard]] auto get_config() -> app_config & { return config_; }
|
||||
|
||||
[[nodiscard]] auto get_config() const -> app_config & { return config_; }
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
handle_rename_file(const std::string &from_api_path,
|
||||
const std::string &to_api_path,
|
||||
const std::string &source_path) -> api_error = 0;
|
||||
|
||||
[[nodiscard]] auto notify_directory_added(const std::string &api_path,
|
||||
const std::string &api_parent) const
|
||||
-> api_error {
|
||||
return const_cast<base_provider *>(this)->notify_directory_added(
|
||||
api_path, api_parent);
|
||||
[[nodiscard]] auto get_config() const -> const app_config & {
|
||||
return config_;
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
notify_directory_added(const std::string &api_path,
|
||||
const std::string &api_parent) -> api_error;
|
||||
[[nodiscard]] auto get_db() const -> rocksdb::DB * { return db_.get(); }
|
||||
|
||||
[[nodiscard]] auto notify_file_added(const std::string &api_path,
|
||||
const std::string &api_parent,
|
||||
std::uint64_t size) const -> api_error {
|
||||
return const_cast<base_provider *>(this)->notify_file_added(
|
||||
api_path, api_parent, size);
|
||||
[[nodiscard]] auto get_file_mgr() -> i_file_manager * { return fm_; }
|
||||
|
||||
[[nodiscard]] auto get_file_mgr() const -> const i_file_manager * {
|
||||
return fm_;
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual auto notify_file_added(const std::string &api_path,
|
||||
const std::string &api_parent,
|
||||
std::uint64_t size)
|
||||
-> api_error = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
populate_directory_items(const std::string &api_path,
|
||||
directory_item_list &list) const -> api_error = 0;
|
||||
|
||||
[[nodiscard]] virtual auto populate_file(const std::string &api_path,
|
||||
api_file &file) const
|
||||
-> api_error = 0;
|
||||
|
||||
auto processed_orphaned_file(const std::string &source_path,
|
||||
const std::string &api_path = "") const -> bool;
|
||||
|
||||
void remove_deleted_files();
|
||||
|
||||
void remove_expired_orphaned_files();
|
||||
|
||||
void remove_unknown_source_files();
|
||||
|
||||
[[nodiscard]] auto remove_item_meta(const std::string &api_path)
|
||||
-> api_error {
|
||||
return meta_db_->remove_item_meta(api_path);
|
||||
}
|
||||
|
||||
void update_filesystem_item(bool directory, const api_error &error,
|
||||
const std::string &api_path,
|
||||
filesystem_item &fsi) const;
|
||||
|
||||
public:
|
||||
[[nodiscard]] auto
|
||||
create_directory_clone_source_meta(const std::string &source_api_path,
|
||||
const std::string &api_path)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto create_file(const std::string &api_path,
|
||||
api_meta_map &meta) -> 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_items(const std::string &api_path,
|
||||
directory_item_list &list) const
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto get_file(const std::string &api_path, api_file &file) 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,
|
||||
api_file &f,
|
||||
filesystem_item &fsi) const
|
||||
-> api_error override;
|
||||
|
||||
@ -161,42 +116,28 @@ public:
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto get_pinned_files() const
|
||||
-> std::vector<std::string> override {
|
||||
return meta_db_->get_pinned_files();
|
||||
}
|
||||
-> std::vector<std::string> override;
|
||||
|
||||
[[nodiscard]] auto get_used_drive_space() const -> std::uint64_t override;
|
||||
[[nodiscard]] auto get_total_item_count() const -> std::uint64_t override;
|
||||
|
||||
[[nodiscard]] auto is_file_writeable(const std::string &) const
|
||||
-> bool override {
|
||||
return true;
|
||||
}
|
||||
[[nodiscard]] auto is_file_writeable(const std::string &api_path) const
|
||||
-> bool override;
|
||||
|
||||
[[nodiscard]] auto remove_item_meta(const std::string &api_path,
|
||||
const std::string &key)
|
||||
-> api_error override {
|
||||
return meta_db_->remove_item_meta(api_path, key);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto rename_file(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 {
|
||||
return meta_db_->set_item_meta(api_path, key, value);
|
||||
}
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto set_item_meta(const std::string &api_path,
|
||||
const api_meta_map &meta)
|
||||
-> api_error override {
|
||||
return meta_db_->set_item_meta(api_path, meta);
|
||||
}
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto start(api_item_added_callback api_item_added,
|
||||
i_file_manager *fm) -> bool override;
|
||||
i_file_manager *mgr) -> bool override;
|
||||
|
||||
void stop() override;
|
||||
};
|
||||
|
@ -33,6 +33,12 @@ public:
|
||||
|
||||
~encrypt_provider() override = default;
|
||||
|
||||
public:
|
||||
encrypt_provider(const encrypt_provider &) = delete;
|
||||
encrypt_provider(encrypt_provider &&) = delete;
|
||||
auto operator=(const encrypt_provider &) -> encrypt_provider & = delete;
|
||||
auto operator=(encrypt_provider &&) -> encrypt_provider & = delete;
|
||||
|
||||
private:
|
||||
struct reader_info final {
|
||||
std::chrono::system_clock::time_point last_access_time =
|
||||
@ -47,7 +53,7 @@ private:
|
||||
rocksdb::ColumnFamilyHandle *dir_family_{};
|
||||
rocksdb::ColumnFamilyHandle *file_family_{};
|
||||
rocksdb::ColumnFamilyHandle *source_family_{};
|
||||
const std::string DB_NAME = "meta_db";
|
||||
std::string DB_NAME = "meta_db";
|
||||
|
||||
private:
|
||||
i_file_manager *fm_ = nullptr;
|
||||
@ -56,7 +62,7 @@ private:
|
||||
std::recursive_mutex reader_lookup_mtx_{};
|
||||
|
||||
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,
|
||||
const std::string &source_path) -> api_file;
|
||||
|
||||
static void create_item_meta(api_meta_map &meta, bool directory,
|
||||
@ -201,13 +207,12 @@ public:
|
||||
}
|
||||
|
||||
[[nodiscard]] auto start(api_item_added_callback api_item_added,
|
||||
i_file_manager *fm) -> bool override;
|
||||
i_file_manager *mgr) -> bool override;
|
||||
|
||||
void stop() override;
|
||||
|
||||
[[nodiscard]] auto upload_file(const std::string & /*api_path*/,
|
||||
const std::string & /*source_path*/,
|
||||
const std::string & /*encryption_token*/,
|
||||
stop_type & /*stop_requested*/)
|
||||
-> api_error override {
|
||||
return api_error::not_implemented;
|
||||
|
@ -143,13 +143,13 @@ public:
|
||||
-> api_error = 0;
|
||||
|
||||
[[nodiscard]] virtual auto start(api_item_added_callback api_item_added,
|
||||
i_file_manager *fm) -> bool = 0;
|
||||
i_file_manager *mgr) -> bool = 0;
|
||||
|
||||
virtual void stop() = 0;
|
||||
|
||||
[[nodiscard]] virtual auto
|
||||
upload_file(const std::string &api_path, const std::string &source_path,
|
||||
const std::string &encryption_token, stop_type &stop_requested)
|
||||
[[nodiscard]] virtual auto upload_file(const std::string &api_path,
|
||||
const std::string &source_path,
|
||||
stop_type &stop_requested)
|
||||
-> api_error = 0;
|
||||
};
|
||||
} // namespace repertory
|
||||
|
@ -23,65 +23,45 @@
|
||||
#define INCLUDE_PROVIDERS_S3_S3_PROVIDER_HPP_
|
||||
#if defined(REPERTORY_ENABLE_S3)
|
||||
|
||||
#include "db/directory_db.hpp"
|
||||
#include "providers/base_provider.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class app_config;
|
||||
class i_file_manager;
|
||||
class i_s3_comm;
|
||||
class i_http_comm;
|
||||
struct head_object_result;
|
||||
|
||||
class s3_provider final : public base_provider {
|
||||
public:
|
||||
s3_provider(app_config &config, i_s3_comm &s3_comm);
|
||||
s3_provider(app_config &config, i_http_comm &comm);
|
||||
|
||||
~s3_provider() override = default;
|
||||
|
||||
private:
|
||||
i_s3_comm &s3_comm_;
|
||||
public:
|
||||
s3_provider(const s3_provider &) = delete;
|
||||
s3_provider(s3_provider &&) = delete;
|
||||
auto operator=(const s3_provider &) -> s3_provider & = delete;
|
||||
auto operator=(s3_provider &&) -> s3_provider & = delete;
|
||||
|
||||
private:
|
||||
std::unique_ptr<directory_db> directory_db_;
|
||||
std::unique_ptr<std::thread> background_thread_;
|
||||
[[nodiscard]] auto add_if_not_found(api_file &file,
|
||||
const std::string &object_name) const
|
||||
-> api_error;
|
||||
|
||||
private:
|
||||
void create_directories();
|
||||
[[nodiscard]] auto create_path_directories(const std::string &api_path,
|
||||
const std::string &key) const
|
||||
-> api_error;
|
||||
|
||||
void create_parent_directories(const api_file &file, bool directory);
|
||||
[[nodiscard]] auto decrypt_object_name(std::string &object_name) const
|
||||
-> api_error;
|
||||
|
||||
void update_item_meta(directory_item &di) const;
|
||||
|
||||
protected:
|
||||
[[nodiscard]] auto check_file_exists(const std::string &api_path) const
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto handle_rename_file(const std::string &from_api_path,
|
||||
const std::string &to_api_path,
|
||||
const std::string &source_path)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto notify_directory_added(const std::string &api_path,
|
||||
const std::string &api_parent)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto notify_file_added(const std::string &api_path,
|
||||
const std::string &api_parent,
|
||||
std::uint64_t size)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto populate_directory_items(const std::string &api_path,
|
||||
directory_item_list &list) const
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto populate_file(const std::string &api_path,
|
||||
api_file &file) const -> api_error override;
|
||||
[[nodiscard]] auto
|
||||
get_object_info(bool directory, const std::string &api_path,
|
||||
bool &is_encrypted, std::string &object_name,
|
||||
head_object_result &result) const -> api_error;
|
||||
|
||||
public:
|
||||
#ifdef REPERTORY_TESTING
|
||||
void set_callback(api_item_added_callback cb) { api_item_added_ = cb; }
|
||||
#endif // REPERTORY_TESTING
|
||||
|
||||
[[nodiscard]] auto create_directory(const std::string &api_path,
|
||||
api_meta_map &meta) -> api_error override;
|
||||
|
||||
@ -91,18 +71,27 @@ public:
|
||||
[[nodiscard]] auto get_directory_item_count(const std::string &api_path) const
|
||||
-> std::uint64_t override;
|
||||
|
||||
[[nodiscard]] auto get_directory_items(const std::string &api_path,
|
||||
directory_item_list &list) const
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto get_file(const std::string &api_path, api_file &file) const
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto get_file_list(api_file_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_total_drive_space() const -> std::uint64_t override;
|
||||
|
||||
[[nodiscard]] auto get_provider_type() const -> provider_type override {
|
||||
return provider_type::s3;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override {
|
||||
return std::numeric_limits<std::int64_t>::max() / std::int64_t(2);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_total_item_count() 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 false; }
|
||||
|
||||
@ -116,7 +105,7 @@ public:
|
||||
|
||||
[[nodiscard]] auto is_rename_supported() const -> bool override {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
[[nodiscard]] auto read_file_bytes(const std::string &api_path,
|
||||
std::size_t size, std::uint64_t offset,
|
||||
@ -130,14 +119,18 @@ public:
|
||||
[[nodiscard]] auto remove_file(const std::string &api_path)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto rename_file(const std::string &from_api_path,
|
||||
const std::string &to_api_path)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto start(api_item_added_callback api_item_added,
|
||||
i_file_manager *fm) -> bool override;
|
||||
i_file_manager *mgr) -> bool override;
|
||||
|
||||
void stop() override;
|
||||
|
||||
[[nodiscard]] auto
|
||||
upload_file(const std::string &api_path, const std::string &source_path,
|
||||
const std::string &encryption_token, stop_type &stop_requested)
|
||||
[[nodiscard]] auto upload_file(const std::string &api_path,
|
||||
const std::string &source_path,
|
||||
stop_type &stop_requested)
|
||||
-> api_error override;
|
||||
};
|
||||
} // namespace repertory
|
||||
|
@ -22,7 +22,7 @@
|
||||
#ifndef INCLUDE_PROVIDERS_SIA_SIA_PROVIDER_HPP_
|
||||
#define INCLUDE_PROVIDERS_SIA_SIA_PROVIDER_HPP_
|
||||
|
||||
#include "providers/i_provider.hpp"
|
||||
#include "providers/base_provider.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
|
||||
namespace repertory {
|
||||
@ -30,57 +30,35 @@ class app_config;
|
||||
class i_file_manager;
|
||||
class i_http_comm;
|
||||
|
||||
class sia_provider : public i_provider {
|
||||
class sia_provider : public base_provider {
|
||||
public:
|
||||
sia_provider(app_config &config, i_http_comm &comm);
|
||||
|
||||
~sia_provider() override = default;
|
||||
|
||||
private:
|
||||
app_config &config_;
|
||||
i_http_comm &comm_;
|
||||
public:
|
||||
sia_provider(const sia_provider &) = delete;
|
||||
sia_provider(sia_provider &&) = delete;
|
||||
auto operator=(const sia_provider &) -> sia_provider & = delete;
|
||||
auto operator=(sia_provider &&) -> sia_provider & = delete;
|
||||
|
||||
private:
|
||||
const std::string DB_NAME = "meta_db";
|
||||
api_item_added_callback api_item_added_;
|
||||
std::unique_ptr<rocksdb::DB> db_;
|
||||
i_file_manager *fm_ = nullptr;
|
||||
|
||||
private:
|
||||
[[nodiscard]] static auto create_api_file(std::string path,
|
||||
std::uint64_t size) -> api_file;
|
||||
|
||||
[[nodiscard]] static auto create_api_file(std::string path,
|
||||
std::uint64_t size,
|
||||
api_meta_map &meta) -> api_file;
|
||||
|
||||
[[nodiscard]] auto get_object_info(const std::string &api_path,
|
||||
json &object_info) const -> api_error;
|
||||
|
||||
[[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;
|
||||
|
||||
void remove_deleted_files();
|
||||
|
||||
public:
|
||||
[[nodiscard]] auto create_directory(const std::string &api_path,
|
||||
api_meta_map &meta) -> api_error override;
|
||||
|
||||
[[nodiscard]] auto
|
||||
create_directory_clone_source_meta(const std::string &source_api_path,
|
||||
const std::string &api_path)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto get_directory_item_count(const std::string &api_path) const
|
||||
-> std::uint64_t override;
|
||||
|
||||
[[nodiscard]] auto create_file(const std::string &api_path,
|
||||
api_meta_map &meta) -> 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_items(const std::string &api_path,
|
||||
directory_item_list &list) const
|
||||
-> api_error override;
|
||||
@ -95,41 +73,12 @@ public:
|
||||
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
|
||||
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_provider_type() const -> provider_type override {
|
||||
return provider_type::sia;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_total_drive_space() 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 is_direct_only() const -> bool override { return false; }
|
||||
@ -140,9 +89,6 @@ public:
|
||||
[[nodiscard]] auto is_file(const std::string &api_path, bool &exists) const
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto is_file_writeable(const std::string &api_path) const
|
||||
-> bool override;
|
||||
|
||||
[[nodiscard]] auto is_online() const -> bool override;
|
||||
|
||||
[[nodiscard]] auto is_rename_supported() const -> bool override {
|
||||
@ -161,31 +107,17 @@ public:
|
||||
[[nodiscard]] auto remove_file(const std::string &api_path)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto remove_item_meta(const std::string &api_path,
|
||||
const std::string &key)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto rename_file(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;
|
||||
|
||||
[[nodiscard]] auto start(api_item_added_callback api_item_added,
|
||||
i_file_manager *fm) -> bool override;
|
||||
i_file_manager *mgr) -> bool override;
|
||||
|
||||
void stop() override;
|
||||
|
||||
[[nodiscard]] auto upload_file(const std::string &api_path,
|
||||
const std::string &source_path,
|
||||
const std::string & /* encryption_token */,
|
||||
stop_type &stop_requested)
|
||||
-> api_error override;
|
||||
};
|
||||
|
@ -22,8 +22,8 @@
|
||||
#ifndef INCLUDE_TYPES_REMOTE_HPP_
|
||||
#define INCLUDE_TYPES_REMOTE_HPP_
|
||||
|
||||
#define PACKET_SERVICE_FUSE std::uint32_t(1)
|
||||
#define PACKET_SERVICE_WINFSP std::uint32_t(2)
|
||||
#define PACKET_SERVICE_FUSE 1U
|
||||
#define PACKET_SERVICE_WINFSP 2U
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PACKET_SERVICE_FLAGS PACKET_SERVICE_WINFSP
|
||||
@ -44,48 +44,51 @@ using group_id = std::uint32_t;
|
||||
using user_id = std::uint32_t;
|
||||
|
||||
enum class open_flags : std::uint32_t {
|
||||
read_only = 0u,
|
||||
write_only = 1u,
|
||||
read_write = 2u,
|
||||
create = 4u,
|
||||
excl = 8u,
|
||||
no_ctty = 16u,
|
||||
truncate = 32u,
|
||||
append = 64u,
|
||||
non_blocking = 128u,
|
||||
sync = 256u,
|
||||
async = 512u,
|
||||
directory = 1024u,
|
||||
no_follow = 2048u,
|
||||
clo_exec = 4096u,
|
||||
direct = 8192u,
|
||||
no_atime = 16384u,
|
||||
path = 32768u,
|
||||
temp_file = 65536u,
|
||||
dsync = 131072u,
|
||||
read_only = 0U,
|
||||
write_only = 1U,
|
||||
read_write = 2U,
|
||||
create = 4U,
|
||||
excl = 8U,
|
||||
no_ctty = 16U,
|
||||
truncate = 32U,
|
||||
append = 64U,
|
||||
non_blocking = 128U,
|
||||
sync = 256U,
|
||||
async = 512U,
|
||||
directory = 1024U,
|
||||
no_follow = 2048U,
|
||||
clo_exec = 4096U,
|
||||
direct = 8192U,
|
||||
no_atime = 16384U,
|
||||
path = 32768U,
|
||||
temp_file = 65536U,
|
||||
dsync = 131072U,
|
||||
};
|
||||
|
||||
inline auto operator|(const open_flags &a, const open_flags &b) -> open_flags {
|
||||
inline auto operator|(const open_flags &flag_1, const open_flags &flag_2)
|
||||
-> open_flags {
|
||||
using t = std::underlying_type_t<open_flags>;
|
||||
return static_cast<open_flags>(static_cast<t>(a) | static_cast<t>(b));
|
||||
return static_cast<open_flags>(static_cast<t>(flag_1) |
|
||||
static_cast<t>(flag_2));
|
||||
}
|
||||
|
||||
#ifdef __GNUG__
|
||||
__attribute__((unused))
|
||||
#endif
|
||||
inline auto
|
||||
operator|=(open_flags &a, const open_flags &b) -> open_flags & {
|
||||
a = a | b;
|
||||
return a;
|
||||
operator|=(open_flags &flag_1, const open_flags &flag_2) -> open_flags & {
|
||||
flag_1 = flag_1 | flag_2;
|
||||
return flag_1;
|
||||
}
|
||||
|
||||
#ifdef __GNUG__
|
||||
__attribute__((unused))
|
||||
#endif
|
||||
inline auto
|
||||
operator&(const open_flags &a, const open_flags &b) -> open_flags {
|
||||
operator&(const open_flags &flag_1, const open_flags &flag_2) -> open_flags {
|
||||
using t = std::underlying_type_t<open_flags>;
|
||||
return static_cast<open_flags>(static_cast<t>(a) & static_cast<t>(b));
|
||||
return static_cast<open_flags>(static_cast<t>(flag_1) &
|
||||
static_cast<t>(flag_2));
|
||||
}
|
||||
|
||||
#pragma pack(1)
|
||||
|
@ -29,7 +29,6 @@ const std::string META_BACKUP = "backup";
|
||||
const std::string META_CHANGED = "changed";
|
||||
const std::string META_CREATION = "creation";
|
||||
const std::string META_DIRECTORY = "directory";
|
||||
const std::string META_ENCRYPTION_TOKEN = "token";
|
||||
const std::string META_GID = "gid";
|
||||
const std::string META_ID = "id";
|
||||
const std::string META_KEY = "key";
|
||||
@ -43,24 +42,10 @@ const std::string META_UID = "uid";
|
||||
const std::string META_WRITTEN = "written";
|
||||
|
||||
const std::vector<std::string> META_USED_NAMES = {
|
||||
META_ACCESSED,
|
||||
META_ATTRIBUTES,
|
||||
META_BACKUP,
|
||||
META_CHANGED,
|
||||
META_CREATION,
|
||||
META_DIRECTORY,
|
||||
META_ENCRYPTION_TOKEN,
|
||||
META_GID,
|
||||
META_ID,
|
||||
META_KEY,
|
||||
META_MODE,
|
||||
META_MODIFIED,
|
||||
META_OSXFLAGS,
|
||||
META_PINNED,
|
||||
META_SIZE,
|
||||
META_SOURCE,
|
||||
META_UID,
|
||||
META_WRITTEN,
|
||||
META_ACCESSED, META_ATTRIBUTES, META_BACKUP, META_CHANGED, META_CREATION,
|
||||
META_DIRECTORY, META_GID, META_ID, META_KEY, META_MODE,
|
||||
META_MODIFIED, META_OSXFLAGS, META_PINNED, META_SIZE, META_SOURCE,
|
||||
META_UID, META_WRITTEN,
|
||||
};
|
||||
|
||||
using api_meta_map = std::map<std::string, std::string>;
|
||||
@ -139,6 +124,12 @@ enum class exit_code : std::int32_t {
|
||||
init_failed = -18,
|
||||
};
|
||||
|
||||
enum http_error_codes : std::int32_t {
|
||||
ok = 200,
|
||||
multiple_choices = 300,
|
||||
not_found = 404,
|
||||
};
|
||||
|
||||
enum class lock_result {
|
||||
success,
|
||||
locked,
|
||||
@ -149,39 +140,37 @@ enum class provider_type : std::size_t {
|
||||
sia,
|
||||
remote,
|
||||
s3,
|
||||
passthrough,
|
||||
encrypt,
|
||||
unknown,
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
struct open_file_data {
|
||||
void *directory_buffer = nullptr;
|
||||
void *directory_buffer{};
|
||||
};
|
||||
#else
|
||||
using open_file_data = int;
|
||||
#endif
|
||||
|
||||
struct api_file {
|
||||
std::string api_path{};
|
||||
std::string api_parent{};
|
||||
std::uint64_t accessed_date = 0u;
|
||||
std::uint64_t changed_date = 0u;
|
||||
std::uint64_t creation_date = 0u;
|
||||
std::string encryption_token{};
|
||||
std::uint64_t file_size = 0u;
|
||||
std::string key{};
|
||||
std::uint64_t modified_date = 0u;
|
||||
std::string source_path{};
|
||||
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 {
|
||||
std::string api_path{};
|
||||
std::string api_parent{};
|
||||
bool directory = false;
|
||||
std::uint64_t size = 0u;
|
||||
std::string api_path;
|
||||
std::string api_parent;
|
||||
bool directory{false};
|
||||
std::uint64_t size{};
|
||||
api_meta_map meta{};
|
||||
bool resolved = false;
|
||||
bool resolved{false};
|
||||
|
||||
[[nodiscard]] static auto from_json(const json &item) -> directory_item {
|
||||
directory_item ret{};
|
||||
@ -203,27 +192,22 @@ struct directory_item {
|
||||
};
|
||||
|
||||
struct filesystem_item {
|
||||
std::string api_path{};
|
||||
std::string api_parent{};
|
||||
bool directory = false;
|
||||
std::string encryption_token{};
|
||||
std::uint64_t size = 0u;
|
||||
std::string source_path{};
|
||||
|
||||
[[nodiscard]] auto is_encrypted() const -> bool {
|
||||
return not encryption_token.empty();
|
||||
}
|
||||
std::string api_path;
|
||||
std::string api_parent;
|
||||
bool directory{false};
|
||||
std::uint64_t size{};
|
||||
std::string source_path;
|
||||
};
|
||||
|
||||
struct host_config {
|
||||
std::string agent_string{};
|
||||
std::string api_password{};
|
||||
std::string api_user{};
|
||||
std::uint16_t api_port = 0u;
|
||||
std::string host_name_or_ip = "localhost";
|
||||
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 = 60000u;
|
||||
std::string protocol{"http"};
|
||||
std::uint32_t timeout_ms{60000U};
|
||||
|
||||
auto operator==(const host_config &hc) const noexcept -> bool {
|
||||
if (&hc != this) {
|
||||
@ -275,29 +259,25 @@ from_json(const json &j, host_config &hc) {
|
||||
}
|
||||
|
||||
struct http_range {
|
||||
std::uint64_t begin = 0u;
|
||||
std::uint64_t end = 0u;
|
||||
};
|
||||
|
||||
struct passthrough_config {
|
||||
std::string location{};
|
||||
std::string name{};
|
||||
std::uint64_t begin;
|
||||
std::uint64_t end;
|
||||
};
|
||||
|
||||
struct encrypt_config {
|
||||
std::string encryption_token{};
|
||||
std::string path{};
|
||||
std::string encryption_token;
|
||||
std::string path;
|
||||
};
|
||||
|
||||
struct s3_config {
|
||||
std::string access_key{};
|
||||
std::string bucket{};
|
||||
std::uint16_t cache_timeout_secs = 60u;
|
||||
std::string encryption_token{};
|
||||
std::string access_key;
|
||||
std::string bucket;
|
||||
std::uint16_t cache_timeout_secs{60U};
|
||||
std::string encryption_token;
|
||||
std::string region = "any";
|
||||
std::string secret_key{};
|
||||
std::uint32_t timeout_ms = 60000u;
|
||||
std::string secret_key;
|
||||
std::uint32_t timeout_ms{60000U};
|
||||
std::string url;
|
||||
bool use_path_style{false};
|
||||
bool use_region_in_url{false};
|
||||
};
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
// NOLINTBEGIN
|
||||
#ifndef _MACARON_BASE64_H_
|
||||
#define _MACARON_BASE64_H_
|
||||
|
||||
@ -25,11 +26,22 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunknown-warning-option"
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#pragma GCC diagnostic ignored "-Wuseless-cast"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace macaron {
|
||||
namespace Base64 {
|
||||
namespace macaron::Base64 {
|
||||
static std::string Encode(const char *data, const size_t &len) {
|
||||
static constexpr char sEncodingTable[] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
@ -135,7 +147,16 @@ static std::string Encode(const char *data, const size_t &len) {
|
||||
|
||||
return out;
|
||||
}
|
||||
} // namespace Base64
|
||||
} // namespace macaron
|
||||
} // namespace macaron::Base64
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif /* _MACARON_BASE64_H_ */
|
||||
|
||||
// NOLINTEND
|
||||
|
@ -34,8 +34,6 @@ static const option data_directory_option = {"-dd", "--data_directory"};
|
||||
static const option encrypt_option = {"-en", "--encrypt"};
|
||||
static const option drive_information_option = {"-di", "--drive_information"};
|
||||
#if defined(REPERTORY_ENABLE_S3)
|
||||
static const option create_directory_option = {"-cd", "--create_directory"};
|
||||
static const option list_objects_option = {"-lo", "--list_objects"};
|
||||
static const option name_option = {"-na", "--name"};
|
||||
static const option s3_option = {"-s3", "--s3"};
|
||||
#endif // defined(REPERTORY_ENABLE_S3)
|
||||
@ -67,8 +65,6 @@ static const std::vector<option> option_list = {
|
||||
#if defined(REPERTORY_ENABLE_S3)
|
||||
s3_option,
|
||||
name_option,
|
||||
create_directory_option,
|
||||
list_objects_option,
|
||||
#endif // defined(REPERTORY_ENABLE_S3)
|
||||
generate_config_option,
|
||||
get_option,
|
||||
|
@ -30,11 +30,15 @@ using key_type = std::array<unsigned char, 32U>;
|
||||
|
||||
class encrypting_reader final {
|
||||
public:
|
||||
encrypting_reader(
|
||||
const std::string &file_name, const std::string &source_path,
|
||||
stop_type &stop_requested, const std::string &token,
|
||||
std::optional<std::string> relative_parent_path = std::nullopt,
|
||||
const size_t error_return = 0);
|
||||
encrypting_reader(const std::string &file_name,
|
||||
const std::string &source_path, stop_type &stop_requested,
|
||||
const std::string &token,
|
||||
std::optional<std::string> relative_parent_path,
|
||||
std::size_t error_return = 0U);
|
||||
|
||||
encrypting_reader(const std::string &encrypted_file_path,
|
||||
const std::string &source_path, stop_type &stop_requested,
|
||||
const std::string &token, std::size_t error_return = 0U);
|
||||
|
||||
encrypting_reader(
|
||||
const std::string &encrypted_file_path, const std::string &source_path,
|
||||
@ -42,9 +46,13 @@ public:
|
||||
std::vector<std::array<unsigned char,
|
||||
crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>
|
||||
iv_list,
|
||||
const size_t error_return = 0);
|
||||
std::size_t error_return = 0U);
|
||||
|
||||
encrypting_reader(const encrypting_reader &r);
|
||||
encrypting_reader(const encrypting_reader &reader);
|
||||
encrypting_reader(encrypting_reader &&) = delete;
|
||||
|
||||
auto operator=(const encrypting_reader &) -> encrypting_reader & = delete;
|
||||
auto operator=(encrypting_reader &&) -> encrypting_reader & = delete;
|
||||
|
||||
~encrypting_reader();
|
||||
|
||||
@ -62,11 +70,11 @@ private:
|
||||
std::vector<
|
||||
std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>
|
||||
iv_list_;
|
||||
std::size_t last_data_chunk_ = 0u;
|
||||
std::size_t last_data_chunk_size_ = 0u;
|
||||
std::uint64_t read_offset_ = 0u;
|
||||
std::size_t last_data_chunk_{};
|
||||
std::size_t last_data_chunk_size_{};
|
||||
std::uint64_t read_offset_{};
|
||||
native_file_ptr source_file_;
|
||||
std::uint64_t total_size_ = 0u;
|
||||
std::uint64_t total_size_{};
|
||||
|
||||
private:
|
||||
static const std::size_t header_size_;
|
||||
|
@ -38,11 +38,13 @@ void calculate_allocation_size(bool directory, std::uint64_t file_size,
|
||||
|
||||
template <typename t>
|
||||
[[nodiscard]] auto collection_excludes(t collection,
|
||||
const typename t::value_type &v) -> bool;
|
||||
const typename t::value_type &val)
|
||||
-> bool;
|
||||
|
||||
template <typename t>
|
||||
[[nodiscard]] auto collection_includes(t collection,
|
||||
const typename t::value_type &v) -> bool;
|
||||
const typename t::value_type &val)
|
||||
-> bool;
|
||||
|
||||
[[nodiscard]] auto compare_version_strings(std::string version1,
|
||||
std::string version2) -> int;
|
||||
@ -53,7 +55,8 @@ template <typename t>
|
||||
|
||||
[[nodiscard]] auto create_uuid_string() -> std::string;
|
||||
|
||||
[[nodiscard]] auto create_volume_label(const provider_type &pt) -> std::string;
|
||||
[[nodiscard]] auto create_volume_label(const provider_type &prov)
|
||||
-> std::string;
|
||||
|
||||
template <typename t>
|
||||
[[nodiscard]] auto divide_with_ceiling(const t &n, const t &d) -> t;
|
||||
@ -66,7 +69,7 @@ template <typename t>
|
||||
-> std::string;
|
||||
|
||||
template <typename t>
|
||||
[[nodiscard]] auto from_hex_string(const std::string &str, t &v) -> bool;
|
||||
[[nodiscard]] auto from_hex_string(const std::string &str, t &val) -> bool;
|
||||
|
||||
[[nodiscard]] auto generate_random_string(std::uint16_t length) -> std::string;
|
||||
|
||||
@ -77,7 +80,7 @@ template <typename t>
|
||||
|
||||
[[nodiscard]] auto get_file_time_now() -> std::uint64_t;
|
||||
|
||||
void get_local_time_now(struct tm &localTime);
|
||||
void get_local_time_now(struct tm &local_time);
|
||||
|
||||
[[nodiscard]] auto get_next_available_port(std::uint16_t first_port,
|
||||
std::uint16_t &available_port)
|
||||
@ -85,11 +88,12 @@ void get_local_time_now(struct tm &localTime);
|
||||
|
||||
[[nodiscard]] auto get_time_now() -> std::uint64_t;
|
||||
|
||||
template <typename t>
|
||||
[[nodiscard]] auto random_between(const t &begin, const t &end) -> t;
|
||||
template <typename data_type>
|
||||
[[nodiscard]] auto random_between(const data_type &begin, const data_type &end)
|
||||
-> data_type;
|
||||
|
||||
template <typename t>
|
||||
void remove_element_from(t &v, const typename t::value_type &value);
|
||||
void remove_element_from(t &collection, const typename t::value_type &val);
|
||||
|
||||
[[nodiscard]] auto reset_curl(CURL *curl_handle) -> CURL *;
|
||||
|
||||
@ -97,28 +101,30 @@ void remove_element_from(t &v, const typename t::value_type &value);
|
||||
-> bool;
|
||||
|
||||
void spin_wait_for_mutex(std::function<bool()> complete,
|
||||
std::condition_variable &cv, std::mutex &mtx,
|
||||
const std::string &txt = "");
|
||||
std::condition_variable &cond, std::mutex &mtx,
|
||||
const std::string &text = "");
|
||||
|
||||
void spin_wait_for_mutex(bool &complete, std::condition_variable &cv,
|
||||
std::mutex &mtx, const std::string &txt = "");
|
||||
void spin_wait_for_mutex(bool &complete, std::condition_variable &cond,
|
||||
std::mutex &mtx, const std::string &text = "");
|
||||
|
||||
template <typename t>
|
||||
[[nodiscard]] auto to_hex_string(const t &v) -> std::string;
|
||||
template <typename collection_t>
|
||||
[[nodiscard]] auto to_hex_string(const collection_t &collection) -> std::string;
|
||||
|
||||
// template implementations
|
||||
template <typename t>
|
||||
[[nodiscard]] auto collection_excludes(t collection,
|
||||
const typename t::value_type &v)
|
||||
const typename t::value_type &val)
|
||||
-> bool {
|
||||
return std::find(collection.begin(), collection.end(), v) == collection.end();
|
||||
return std::find(collection.begin(), collection.end(), val) ==
|
||||
collection.end();
|
||||
}
|
||||
|
||||
template <typename t>
|
||||
[[nodiscard]] auto collection_includes(t collection,
|
||||
const typename t::value_type &v)
|
||||
const typename t::value_type &val)
|
||||
-> bool {
|
||||
return std::find(collection.begin(), collection.end(), v) != collection.end();
|
||||
return std::find(collection.begin(), collection.end(), val) !=
|
||||
collection.end();
|
||||
}
|
||||
|
||||
template <typename t>
|
||||
@ -127,12 +133,14 @@ template <typename t>
|
||||
}
|
||||
|
||||
template <typename t>
|
||||
[[nodiscard]] auto from_hex_string(const std::string &str, t &v) -> bool {
|
||||
v.clear();
|
||||
if (not(str.length() % 2u)) {
|
||||
for (std::size_t i = 0u; i < str.length(); i += 2u) {
|
||||
v.emplace_back(static_cast<typename t::value_type>(
|
||||
strtol(str.substr(i, 2u).c_str(), nullptr, 16)));
|
||||
[[nodiscard]] auto from_hex_string(const std::string &str, t &val) -> bool {
|
||||
static constexpr const auto base16 = 16;
|
||||
|
||||
val.clear();
|
||||
if (not(str.length() % 2U)) {
|
||||
for (std::size_t i = 0U; i < str.length(); i += 2U) {
|
||||
val.emplace_back(static_cast<typename t::value_type>(
|
||||
strtol(str.substr(i, 2U).c_str(), nullptr, base16)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -140,33 +148,33 @@ template <typename t>
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename t>
|
||||
[[nodiscard]] auto random_between(const t &begin, const t &end) -> t {
|
||||
srand(static_cast<unsigned int>(get_time_now()));
|
||||
return begin + rand() % ((end + 1) - begin);
|
||||
template <typename data_type>
|
||||
[[nodiscard]] auto random_between(const data_type &begin, const data_type &end)
|
||||
-> data_type {
|
||||
return begin + repertory_rand<data_type>() % ((end + 1) - begin);
|
||||
}
|
||||
|
||||
template <typename t>
|
||||
void remove_element_from(t &v, const typename t::value_type &value) {
|
||||
v.erase(std::remove(v.begin(), v.end(), value), v.end());
|
||||
template <typename collection_t>
|
||||
void remove_element_from(collection_t &collection,
|
||||
const typename collection_t::value_type &value) {
|
||||
collection.erase(std::remove(collection.begin(), collection.end(), value),
|
||||
collection.end());
|
||||
}
|
||||
|
||||
template <typename t>
|
||||
[[nodiscard]] auto to_hex_string(const t &value) -> std::string {
|
||||
std::string ret{};
|
||||
template <typename collection_t>
|
||||
[[nodiscard]] auto to_hex_string(const collection_t &collection)
|
||||
-> std::string {
|
||||
static_assert(sizeof(typename collection_t::value_type) == 1U,
|
||||
"value_type must be 1 byte in size");
|
||||
static constexpr const auto mask = 0xFF;
|
||||
|
||||
std::array<char, 3> h{};
|
||||
for (const auto &num : value) {
|
||||
#ifdef _WIN32
|
||||
sprintf_s(h.data(), h.size() - 1U, "%x", static_cast<std::uint8_t>(num));
|
||||
#else
|
||||
sprintf(h.data(), "%x", static_cast<std::uint8_t>(num));
|
||||
#endif
|
||||
|
||||
ret += (strlen(h.data()) == 1) ? std::string("0") + h.data() : h.data();
|
||||
std::stringstream stream;
|
||||
for (const auto &val : collection) {
|
||||
stream << std::setfill('0') << std::setw(2) << std::hex
|
||||
<< (static_cast<std::uint32_t>(val) & mask);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return stream.str();
|
||||
}
|
||||
} // namespace repertory::utils
|
||||
|
||||
|
@ -1,331 +0,0 @@
|
||||
/*
|
||||
** MODIFIED BY <scott.e.graves@gmail.com>
|
||||
** - Modifications for C++11
|
||||
** - Memory leak avoidance
|
||||
**
|
||||
** OSSP uuid - Universally Unique Identifier
|
||||
** Copyright (c) 2004-2008 Ralf S. Engelschall <rse@engelschall.com>
|
||||
** Copyright (c) 2004-2008 The OSSP Project <http://www.ossp.org/>
|
||||
**
|
||||
** This file is part of OSSP uuid, a library for the generation
|
||||
** of UUIDs which can found at http://www.ossp.org/pkg/lib/uuid/
|
||||
**
|
||||
** Permission to use, copy, modify, and distribute this software for
|
||||
** any purpose with or without fee is hereby granted, provided that
|
||||
** the above copyright notice and this permission notice appear in all
|
||||
** copies.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
|
||||
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
** SUCH DAMAGE.
|
||||
**
|
||||
** uuid++.hh: library C++ API definition
|
||||
*/
|
||||
#if __linux__
|
||||
|
||||
#ifndef __UUIDXX_HH__
|
||||
#define __UUIDXX_HH__
|
||||
#include <cstdarg>
|
||||
#include <string>
|
||||
#include <exception>
|
||||
#include <vector>
|
||||
#include <uuid.h>
|
||||
|
||||
namespace repertory {
|
||||
/* UUID exception class */
|
||||
class uuid_error_t : public virtual std::exception {
|
||||
public:
|
||||
uuid_error_t() : rc(UUID_RC_OK){};
|
||||
|
||||
explicit uuid_error_t(const uuid_rc_t &code) : rc(code) {}
|
||||
|
||||
private:
|
||||
const uuid_rc_t rc;
|
||||
|
||||
public:
|
||||
uuid_rc_t code() const { return rc; };
|
||||
|
||||
const char *what() const noexcept override {
|
||||
static std::string ret;
|
||||
if (ret.empty()) {
|
||||
auto *p = uuid_error(rc);
|
||||
ret = std::string(p, strlen(p));
|
||||
free(p);
|
||||
}
|
||||
return ret.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
/* UUID object class */
|
||||
class uuid {
|
||||
public:
|
||||
/* construction & destruction */
|
||||
|
||||
/* standard constructor */
|
||||
uuid() {
|
||||
uuid_rc_t rc;
|
||||
if ((rc = uuid_create(&ctx)) != UUID_RC_OK)
|
||||
throw uuid_error_t(rc);
|
||||
}
|
||||
|
||||
/* copy constructor */
|
||||
uuid(const uuid &obj) {
|
||||
/* Notice: the copy constructor is the same as the assignment
|
||||
operator (with the object as the argument) below, except that
|
||||
(1) no check for self-assignment is required, (2) no existing
|
||||
internals have to be destroyed and (3) no return value is given back. */
|
||||
uuid_rc_t rc;
|
||||
if ((rc = uuid_clone(obj.ctx, &ctx)) != UUID_RC_OK)
|
||||
throw uuid_error_t(rc);
|
||||
}
|
||||
|
||||
/* import constructor */
|
||||
explicit uuid(const uuid_t *obj) {
|
||||
uuid_rc_t rc;
|
||||
if (obj == nullptr)
|
||||
throw uuid_error_t(UUID_RC_ARG);
|
||||
if ((rc = uuid_clone(obj, &ctx)) != UUID_RC_OK)
|
||||
throw uuid_error_t(rc);
|
||||
}
|
||||
|
||||
/* import constructor */
|
||||
explicit uuid(const std::vector<void *> &bin) {
|
||||
uuid_rc_t rc;
|
||||
if (bin.empty())
|
||||
throw uuid_error_t(UUID_RC_ARG);
|
||||
if ((rc = uuid_create(&ctx)) != UUID_RC_OK)
|
||||
throw uuid_error_t(rc);
|
||||
import(bin);
|
||||
}
|
||||
|
||||
/* import constructor */
|
||||
explicit uuid(const std::string &str) {
|
||||
uuid_rc_t rc;
|
||||
if (str.empty())
|
||||
throw uuid_error_t(UUID_RC_ARG);
|
||||
if ((rc = uuid_create(&ctx)) != UUID_RC_OK)
|
||||
throw uuid_error_t(rc);
|
||||
import(str);
|
||||
}
|
||||
|
||||
/* move constructor */
|
||||
uuid(uuid &&obj) noexcept : ctx(obj.ctx) {}
|
||||
|
||||
/* destructor */
|
||||
~uuid() { uuid_destroy(ctx); }
|
||||
|
||||
private:
|
||||
uuid_t *ctx = nullptr;
|
||||
|
||||
public:
|
||||
/* copying & cloning */
|
||||
|
||||
/* copy assignment operator */
|
||||
uuid &operator=(const uuid &obj) {
|
||||
uuid_rc_t rc;
|
||||
if (this != &obj) {
|
||||
if ((rc = uuid_destroy(ctx)) != UUID_RC_OK)
|
||||
throw uuid_error_t(rc);
|
||||
if ((rc = uuid_clone(obj.ctx, &ctx)) != UUID_RC_OK)
|
||||
throw uuid_error_t(rc);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* move assignment operator */
|
||||
uuid &operator=(uuid &&obj) {
|
||||
if (this != &obj) {
|
||||
ctx = obj.ctx;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* import assignment operator */
|
||||
uuid &operator=(const uuid_t *obj) {
|
||||
uuid_rc_t rc;
|
||||
if (obj == nullptr)
|
||||
throw uuid_error_t(UUID_RC_ARG);
|
||||
if ((rc = uuid_clone(obj, &ctx)) != UUID_RC_OK)
|
||||
throw uuid_error_t(rc);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* import assignment operator */
|
||||
uuid &operator=(const std::vector<void *> &bin) {
|
||||
if (bin.empty())
|
||||
throw uuid_error_t(UUID_RC_ARG);
|
||||
import(bin);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* import assignment operator */
|
||||
uuid &operator=(const std::string &str) {
|
||||
if (str.empty())
|
||||
throw uuid_error_t(UUID_RC_ARG);
|
||||
import(str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* regular method */
|
||||
uuid clone() { return uuid(*this); }
|
||||
|
||||
/* content generation */
|
||||
|
||||
/* regular method */
|
||||
void load(const std::string &name) {
|
||||
uuid_rc_t rc;
|
||||
if (name.empty())
|
||||
throw uuid_error_t(UUID_RC_ARG);
|
||||
if ((rc = uuid_load(ctx, &name[0])) != UUID_RC_OK)
|
||||
throw uuid_error_t(rc);
|
||||
}
|
||||
|
||||
/* regular method */
|
||||
void make(unsigned int mode, ...) {
|
||||
uuid_rc_t rc;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, mode);
|
||||
if ((mode & UUID_MAKE_V3) || (mode & UUID_MAKE_V5)) {
|
||||
const uuid *ns = (const uuid *)va_arg(ap, const uuid *);
|
||||
const char *name = (const char *)va_arg(ap, char *);
|
||||
if (ns == nullptr || name == nullptr)
|
||||
throw uuid_error_t(UUID_RC_ARG);
|
||||
rc = uuid_make(ctx, mode, ns->ctx, name);
|
||||
} else
|
||||
rc = uuid_make(ctx, mode);
|
||||
va_end(ap);
|
||||
if (rc != UUID_RC_OK)
|
||||
throw uuid_error_t(rc);
|
||||
}
|
||||
|
||||
/* content comparison */
|
||||
|
||||
/* regular method */
|
||||
int isnil() {
|
||||
uuid_rc_t rc;
|
||||
int rv;
|
||||
|
||||
if ((rc = uuid_isnil(ctx, &rv)) != UUID_RC_OK)
|
||||
throw uuid_error_t(rc);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* regular method */
|
||||
int compare(const uuid &obj) {
|
||||
uuid_rc_t rc;
|
||||
int rv;
|
||||
|
||||
if ((rc = uuid_compare(ctx, obj.ctx, &rv)) != UUID_RC_OK)
|
||||
throw uuid_error_t(rc);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* comparison operator */
|
||||
int operator==(const uuid &obj) { return (compare(obj) == 0); }
|
||||
|
||||
/* comparison operator */
|
||||
int operator!=(const uuid &obj) { return (compare(obj) != 0); }
|
||||
|
||||
/* comparison operator */
|
||||
int operator<(const uuid &obj) { return (compare(obj) < 0); }
|
||||
|
||||
/* comparison operator */
|
||||
int operator<=(const uuid &obj) { return (compare(obj) <= 0); }
|
||||
|
||||
/* comparison operator */
|
||||
int operator>(const uuid &obj) { return (compare(obj) > 0); }
|
||||
|
||||
/* comparison operator */
|
||||
int operator>=(const uuid &obj) { return (compare(obj) >= 0); }
|
||||
|
||||
/* content importing & exporting */
|
||||
|
||||
/* regular method */
|
||||
void import(const std::vector<void *> &bin) {
|
||||
uuid_rc_t rc;
|
||||
if ((rc = uuid_import(ctx, UUID_FMT_BIN, &bin[0], UUID_LEN_BIN)) !=
|
||||
UUID_RC_OK)
|
||||
throw uuid_error_t(rc);
|
||||
}
|
||||
|
||||
/* regular method */
|
||||
void import(const std::string &str) {
|
||||
uuid_rc_t rc;
|
||||
if ((rc = uuid_import(ctx, UUID_FMT_STR, &str[0], UUID_LEN_STR)) !=
|
||||
UUID_RC_OK)
|
||||
if ((rc = uuid_import(ctx, UUID_FMT_SIV, &str[0], UUID_LEN_SIV)) !=
|
||||
UUID_RC_OK)
|
||||
throw uuid_error_t(rc);
|
||||
}
|
||||
|
||||
/* regular method */
|
||||
std::vector<void *> binary() {
|
||||
uuid_rc_t rc;
|
||||
void *bin = nullptr;
|
||||
if ((rc = uuid_export(ctx, UUID_FMT_BIN, &bin, nullptr)) != UUID_RC_OK)
|
||||
throw uuid_error_t(rc);
|
||||
|
||||
std::vector<void *> data;
|
||||
data.resize(UUID_LEN_BIN);
|
||||
memcpy(&data[0], bin, UUID_LEN_BIN);
|
||||
free(bin);
|
||||
return data;
|
||||
}
|
||||
|
||||
/* regular method */
|
||||
std::string string() {
|
||||
uuid_rc_t rc;
|
||||
char *str = nullptr;
|
||||
if ((rc = uuid_export(ctx, UUID_FMT_STR, (void **)&str, nullptr)) !=
|
||||
UUID_RC_OK)
|
||||
throw uuid_error_t(rc);
|
||||
std::string data;
|
||||
data.resize(UUID_LEN_STR + 1);
|
||||
memcpy(&data[0], str, UUID_LEN_STR);
|
||||
free(str);
|
||||
return &data[0];
|
||||
}
|
||||
|
||||
/* regular method */
|
||||
std::string integer() {
|
||||
uuid_rc_t rc;
|
||||
char *str = nullptr;
|
||||
if ((rc = uuid_export(ctx, UUID_FMT_SIV, (void **)&str, nullptr)) !=
|
||||
UUID_RC_OK)
|
||||
throw uuid_error_t(rc);
|
||||
std::string data;
|
||||
data.resize(UUID_LEN_SIV + 1);
|
||||
memcpy(&data[0], str, UUID_LEN_SIV);
|
||||
free(str);
|
||||
return &data[0];
|
||||
}
|
||||
|
||||
/* regular method */
|
||||
std::string summary() {
|
||||
uuid_rc_t rc;
|
||||
char *txt = nullptr;
|
||||
if ((rc = uuid_export(ctx, UUID_FMT_TXT, (void **)&txt, nullptr)) !=
|
||||
UUID_RC_OK)
|
||||
throw uuid_error_t(rc);
|
||||
std::string data(txt, strlen(txt));
|
||||
free(txt);
|
||||
return data;
|
||||
}
|
||||
|
||||
/* regular method */
|
||||
unsigned long version() { return uuid_version(); }
|
||||
};
|
||||
} // namespace repertory
|
||||
#endif /* __UUIDXX_HH__ */
|
||||
|
||||
#endif
|
@ -1,115 +0,0 @@
|
||||
@echo off
|
||||
setlocal
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
set SIGNING_FOLDER=%1
|
||||
set BINARY_FOLDER=%2
|
||||
set SOURCE_FOLDER=%3
|
||||
set OUTPUT_FOLDER=%4
|
||||
|
||||
set PATH=%~dp0%..\bin;!PATH!
|
||||
|
||||
if "%SIGNING_FOLDER%" == "" (
|
||||
call :EXIT_SCRIPT "'SIGNING_FOLDER' is not set (arg1)"
|
||||
)
|
||||
|
||||
if "%BINARY_FOLDER%" == "" (
|
||||
call :EXIT_SCRIPT "'BINARY_FOLDER' is not set (arg2)"
|
||||
)
|
||||
|
||||
if "%SOURCE_FOLDER%" == "" (
|
||||
call :EXIT_SCRIPT "'SOURCE_FOLDER' is not set (arg3)"
|
||||
)
|
||||
|
||||
if "%OUTPUT_FOLDER%" == "" (
|
||||
call :EXIT_SCRIPT "'OUTPUT_FOLDER' is not set (arg4)"
|
||||
)
|
||||
|
||||
call :NORMALIZE "%SIGNING_FOLDER%"
|
||||
set SIGNING_FOLDER=%RETVAL%
|
||||
|
||||
call :NORMALIZE "%BINARY_FOLDER%"
|
||||
set BINARY_FOLDER=%RETVAL%
|
||||
|
||||
call :NORMALIZE "%SOURCE_FOLDER%"
|
||||
set SOURCE_FOLDER=%RETVAL%
|
||||
|
||||
set BUILD_ARCH=Win64
|
||||
set OPENSSL_BIN="c:\OpenSSL-%BUILD_ARCH%\bin\openssl.exe"
|
||||
if NOT EXIST %OPENSSL_BIN% (
|
||||
set OPENSSL_BIN="c:\Program Files\OpenSSL-%BUILD_ARCH%\bin\openssl.exe"
|
||||
set REPERTORY_OPENSSL_ROOT="c:\Program Files\OpenSSL-%BUILD_ARCH%"
|
||||
)
|
||||
|
||||
pushd "%SOURCE_FOLDER%"
|
||||
for /F "tokens=*" %%f in ('git rev-parse --short HEAD') do (set GIT_REV=%%f)
|
||||
for /F "tokens=*" %%f in ('git branch --show-current') do (set GIT_BRANCH=%%f)
|
||||
for /F "tokens=*" %%f in ('grep set(REPERTORY_MAJOR .\CMakeLists.txt ^| sed "s/)//g" ^| awk "{print $2}"') do (set REPERTORY_VERSION=%%f)
|
||||
for /F "tokens=*" %%f in ('grep set(REPERTORY_MINOR .\CMakeLists.txt ^| sed "s/)//g" ^| awk "{print $2}"') do (set REPERTORY_VERSION=%REPERTORY_VERSION%.%%f)
|
||||
for /F "tokens=*" %%f in ('grep set(REPERTORY_REV .\CMakeLists.txt ^| sed "s/)//g" ^| awk "{print $2}"') do (set REPERTORY_VERSION=%REPERTORY_VERSION%.%%f)
|
||||
for /F "tokens=*" %%f in ('grep set(REPERTORY_RELEASE_ITER .\CMakeLists.txt ^| sed "s/)//g" ^| awk "{print $2}"') do (set REPERTORY_VERSION=%REPERTORY_VERSION%-%%f)
|
||||
popd
|
||||
|
||||
if "%GIT_BRANCH%" == "development" (
|
||||
set RELEASE_FOLDER=nightly
|
||||
) else (
|
||||
set RELEASE_FOLDER=%REPERTORY_RELEASE_ITER%
|
||||
)
|
||||
|
||||
call :NORMALIZE "%OUTPUT_FOLDER%\!RELEASE_FOLDER!"
|
||||
set OUTPUT_FOLDER=%RETVAL%
|
||||
|
||||
set OUT_FILE=repertory_%REPERTORY_VERSION%_%GIT_REV%_windows_amd64.zip
|
||||
set OUT_ZIP=%BINARY_FOLDER%\%OUT_FILE%
|
||||
set FILE_LIST=repertory.exe repertory.exe.sha256 repertory.exe.sig winfsp-x64.dll winfsp-x64.dll.sha256 winfsp-x64.dll.sig cacert.pem cacert.pem.sha256 cacert.pem.sig
|
||||
|
||||
pushd "%BINARY_FOLDER%"
|
||||
call :CLEANUP
|
||||
|
||||
call :CREATE_HASH "%BINARY_FOLDER%\repertory.exe"
|
||||
call :CREATE_HASH "%BINARY_FOLDER%\winfsp-x64.dll"
|
||||
call :CREATE_HASH "%BINARY_FOLDER%\cacert.pem"
|
||||
|
||||
(7za u "%OUT_FILE%" %FILE_LIST%) || (7z u "%OUT_FILE%" %FILE_LIST%) || (call :EXIT_SCRIPT "Create repertory zip failed")
|
||||
|
||||
call :CREATE_HASH "%OUT_FILE%"
|
||||
|
||||
copy /y "%OUT_ZIP%" "%OUTPUT_FOLDER%" || call :EXIT_SCRIPT "Copy %OUT_ZIP% to %OUTPUT_FOLDER% failed"
|
||||
copy /y "%OUT_ZIP%.sha256" "%OUTPUT_FOLDER%" || call :EXIT_SCRIPT "Copy %OUT_ZIP%.sha256 to %OUTPUT_FOLDER% failed"
|
||||
copy /y "%OUT_ZIP%.sig" "%OUTPUT_FOLDER%" || call :EXIT_SCRIPT "Copy %OUT_ZIP%.sig to %OUTPUT_FOLDER% failed"
|
||||
|
||||
call :CLEANUP
|
||||
popd
|
||||
goto :END
|
||||
|
||||
:CREATE_HASH
|
||||
call :NORMALIZE %1
|
||||
set HASH_FILE=%RETVAL%
|
||||
|
||||
(%OPENSSL_BIN% dgst -sha256 -sign "%SIGNING_FOLDER%\blockstorage_dev_private.pem" -out "%HASH_FILE%.sig" "%HASH_FILE%") || (call :EXIT_SCRIPT "Create %HASH_FILE% signature failed")
|
||||
(%OPENSSL_BIN% dgst -sha256 -verify "%SIGNING_FOLDER%\blockstorage_dev_public.pem" -signature "%HASH_FILE%.sig" "%HASH_FILE%") || (call :EXIT_SCRIPT "Verify %HASH_FILE% signature failed")
|
||||
((certutil -hashfile "%HASH_FILE%" SHA256 | sed -e "1d" -e "$d" -e "s/\ //g") > "%HASH_FILE%.sha256") || (call :EXIT_SCRIPT "Create %HASH_FILE% sha-256 failed")
|
||||
EXIT /B
|
||||
|
||||
:CLEANUP
|
||||
del /q "%OUT_ZIP%" 1>NUL 2>&1
|
||||
del /q "%OUT_ZIP%.sha256" 1>NUL 2>&1
|
||||
del /q "%OUT_ZIP%.sig" 1>NUL 2>&1
|
||||
del /q "%BINARY_FOLDER%\cacert.pem.sha256" 1>NUL 2>&1
|
||||
del /q "%BINARY_FOLDER%\cacert.pem.sig" 1>NUL 2>&1
|
||||
del /q "%BINARY_FOLDER%\repertory.exe.sha256" 1>NUL 2>&1
|
||||
del /q "%BINARY_FOLDER%\repertory.exe.sig" 1>NUL 2>&1
|
||||
del /q "%BINARY_FOLDER%\winfsp-x64.dll.sha256" 1>NUL 2>&1
|
||||
del /q "%BINARY_FOLDER%\winfsp-x64.dll.sig" 1>NUL 2>&1
|
||||
EXIT /B
|
||||
|
||||
:NORMALIZE
|
||||
SET RETVAL=%~f1
|
||||
exit /B
|
||||
|
||||
:EXIT_SCRIPT
|
||||
echo %1
|
||||
exit 1
|
||||
|
||||
:END
|
||||
echo Done
|
@ -1,44 +0,0 @@
|
||||
@echo off
|
||||
|
||||
set MSVC_BUILD_TYPE=%1
|
||||
set BUILD_CLEAN=%2
|
||||
|
||||
if "%MSVC_BUILD_TYPE%" == "" (
|
||||
echo "Build type not set"
|
||||
exit 1
|
||||
)
|
||||
|
||||
if "%MSVC_BUILD_TYPE%" == "Debug" (
|
||||
set BUILD_FOLDER=debug
|
||||
) else (
|
||||
if "%MSVC_BUILD_TYPE%" == "Release" (
|
||||
set BUILD_FOLDER=release
|
||||
) else (
|
||||
set BUILD_FOLDER=%MSVC_BUILD_TYPE%
|
||||
)
|
||||
set MSVC_BUILD_TYPE=Release
|
||||
)
|
||||
|
||||
if EXIST "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" (
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
|
||||
) else (
|
||||
if EXIST "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat" (
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat"
|
||||
)
|
||||
)
|
||||
|
||||
pushd "%~dp0%"
|
||||
md ..\build2\%BUILD_FOLDER%
|
||||
del /q ..\build2\%BUILD_FOLDER%\librepertory.lib
|
||||
del /q ..\build2\%BUILD_FOLDER%\repertory.exe
|
||||
del /q ..\build2\%BUILD_FOLDER%\unittests.exe
|
||||
|
||||
pushd "..\build2\%BUILD_FOLDER%"
|
||||
cmake ..\.. -G "NMake Makefiles" -DREPERTORY_ENABLE_S3_TESTING=ON -DREPERTORY_ENABLE_S3=ON -DCMAKE_BUILD_TYPE=%MSVC_BUILD_TYPE% || exit 1
|
||||
copy /y compile_commands.json ..
|
||||
if "%BUILD_CLEAN%" == "clean" (
|
||||
nmake clean || exit 1
|
||||
)
|
||||
nmake || exit 1
|
||||
popd
|
||||
popd
|
@ -29,19 +29,19 @@
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
app_config::app_config(const provider_type &pt,
|
||||
app_config::app_config(const provider_type &prov,
|
||||
const std::string &data_directory)
|
||||
: pt_(pt),
|
||||
api_auth_(utils::generate_random_string(48u)),
|
||||
api_port_(default_rpc_port(pt)),
|
||||
: prov_(prov),
|
||||
api_auth_(utils::generate_random_string(48U)),
|
||||
api_port_(default_rpc_port(prov)),
|
||||
api_user_("repertory"),
|
||||
config_changed_(false),
|
||||
data_directory_(
|
||||
data_directory.empty() ? default_data_directory(pt)
|
||||
: ((pt == provider_type::remote) || (pt == provider_type::s3))
|
||||
data_directory.empty() ? default_data_directory(prov)
|
||||
: ((prov == provider_type::remote) || (prov == provider_type::s3))
|
||||
? utils::path::absolute(data_directory)
|
||||
: utils::path::absolute(utils::path::combine(
|
||||
data_directory, {get_provider_name(pt)}))),
|
||||
data_directory, {get_provider_name(prov)}))),
|
||||
download_timeout_secs_(30),
|
||||
enable_chunk_downloader_timeout_(true),
|
||||
enable_comm_duration_events_(false),
|
||||
@ -58,7 +58,7 @@ app_config::app_config(const provider_type &pt,
|
||||
is_remote_mount_(false),
|
||||
low_freq_interval_secs_(60 * 60),
|
||||
max_cache_size_bytes_(20 * 1024 * 1024 * 1024ULL),
|
||||
max_upload_count_(5u),
|
||||
max_upload_count_(5U),
|
||||
min_download_timeout_secs_(5),
|
||||
online_check_retry_secs_(60),
|
||||
orphaned_file_retention_days_(15),
|
||||
@ -68,10 +68,10 @@ app_config::app_config(const provider_type &pt,
|
||||
remote_client_pool_size_(10),
|
||||
remote_host_name_or_ip_(""),
|
||||
remote_max_connections_(20),
|
||||
remote_port_((pt == provider_type::sia) ? 20000
|
||||
: (pt == provider_type::s3) ? 20001
|
||||
: (pt == provider_type::encrypt) ? 20002
|
||||
: 20003),
|
||||
remote_port_((prov == provider_type::sia) ? 20000
|
||||
: (prov == provider_type::s3) ? 20001
|
||||
: (prov == provider_type::encrypt) ? 20002
|
||||
: 20003),
|
||||
remote_receive_timeout_secs_(120),
|
||||
remote_send_timeout_secs_(30),
|
||||
remote_token_(""),
|
||||
@ -80,18 +80,21 @@ app_config::app_config(const provider_type &pt,
|
||||
cache_directory_ = utils::path::combine(data_directory_, {"cache"});
|
||||
log_directory_ = utils::path::combine(data_directory_, {"logs"});
|
||||
|
||||
hc_.agent_string = default_agent_name(pt_);
|
||||
hc_.api_password = get_provider_api_password(pt_);
|
||||
hc_.api_port = default_api_port(pt_);
|
||||
hc_.agent_string = default_agent_name(prov_);
|
||||
hc_.api_password = get_provider_api_password(prov_);
|
||||
hc_.api_port = default_api_port(prov_);
|
||||
|
||||
if (not utils::file::create_full_directory_path(data_directory_))
|
||||
if (not utils::file::create_full_directory_path(data_directory_)) {
|
||||
throw startup_exception("unable to create: " + data_directory_);
|
||||
}
|
||||
|
||||
if (not utils::file::create_full_directory_path(cache_directory_))
|
||||
if (not utils::file::create_full_directory_path(cache_directory_)) {
|
||||
throw startup_exception("unable to create: " + cache_directory_);
|
||||
}
|
||||
|
||||
if (not utils::file::create_full_directory_path(log_directory_))
|
||||
if (not utils::file::create_full_directory_path(log_directory_)) {
|
||||
throw startup_exception("unable to create: " + log_directory_);
|
||||
}
|
||||
|
||||
if (not load()) {
|
||||
save();
|
||||
@ -102,48 +105,51 @@ auto app_config::get_config_file_path() const -> std::string {
|
||||
return utils::path::combine(data_directory_, {"config.json"});
|
||||
}
|
||||
|
||||
auto app_config::default_agent_name(const provider_type &pt) -> std::string {
|
||||
auto app_config::default_agent_name(const provider_type &prov) -> std::string {
|
||||
static const std::array<std::string,
|
||||
static_cast<std::size_t>(provider_type::unknown)>
|
||||
PROVIDER_AGENT_NAMES = {"Sia-Agent", "", "", "", ""};
|
||||
PROVIDER_AGENT_NAMES = {"Sia-Agent", "", "", ""};
|
||||
|
||||
return PROVIDER_AGENT_NAMES[static_cast<std::size_t>(pt)];
|
||||
return PROVIDER_AGENT_NAMES[static_cast<std::size_t>(prov)];
|
||||
}
|
||||
|
||||
auto app_config::default_api_port(const provider_type &pt) -> std::uint16_t {
|
||||
auto app_config::default_api_port(const provider_type &prov) -> std::uint16_t {
|
||||
static const std::array<std::uint16_t,
|
||||
static_cast<std::size_t>(provider_type::unknown)>
|
||||
PROVIDER_API_PORTS = {9980u, 0u, 0u, 0u, 0u};
|
||||
return PROVIDER_API_PORTS[static_cast<std::size_t>(pt)];
|
||||
PROVIDER_API_PORTS = {9980U, 0U, 0U, 0U};
|
||||
return PROVIDER_API_PORTS[static_cast<std::size_t>(prov)];
|
||||
}
|
||||
|
||||
auto app_config::default_data_directory(const provider_type &pt)
|
||||
auto app_config::default_data_directory(const provider_type &prov)
|
||||
-> std::string {
|
||||
#ifdef _WIN32
|
||||
auto data_directory = utils::path::combine(
|
||||
utils::get_local_app_data_directory(),
|
||||
{REPERTORY_DATA_NAME, app_config::get_provider_name(pt)});
|
||||
{REPERTORY_DATA_NAME, app_config::get_provider_name(prov)});
|
||||
#else
|
||||
#ifdef __APPLE__
|
||||
auto data_directory = utils::path::resolve(
|
||||
std::string("~/Library/Application Support/") + REPERTORY_DATA_NAME +
|
||||
'/' + app_config::get_provider_name(pt));
|
||||
'/' + app_config::get_provider_name(prov));
|
||||
#else
|
||||
auto data_directory =
|
||||
utils::path::resolve(std::string("~/.local/") + REPERTORY_DATA_NAME +
|
||||
'/' + app_config::get_provider_name(pt));
|
||||
'/' + app_config::get_provider_name(prov));
|
||||
#endif
|
||||
#endif
|
||||
return data_directory;
|
||||
}
|
||||
|
||||
auto app_config::default_rpc_port(const provider_type &pt) -> std::uint16_t {
|
||||
auto app_config::default_rpc_port(const provider_type &prov) -> std::uint16_t {
|
||||
static const std::array<std::uint16_t,
|
||||
static_cast<std::size_t>(provider_type::unknown)>
|
||||
PROVIDER_RPC_PORTS = {
|
||||
11101u, 11102u, 11103u, 11104u, 11105u,
|
||||
11101U,
|
||||
11102U,
|
||||
11103U,
|
||||
11104U,
|
||||
};
|
||||
return PROVIDER_RPC_PORTS[static_cast<std::size_t>(pt)];
|
||||
return PROVIDER_RPC_PORTS[static_cast<std::size_t>(prov)];
|
||||
}
|
||||
|
||||
auto app_config::get_json() const -> json {
|
||||
@ -209,11 +215,12 @@ auto app_config::get_json() const -> json {
|
||||
{"SecretKey", s3_config_.secret_key},
|
||||
{"TimeoutMs", s3_config_.timeout_ms},
|
||||
{"URL", s3_config_.url},
|
||||
{"UsePathStyle", s3_config_.use_path_style},
|
||||
{"UseRegionInURL", s3_config_.use_region_in_url},
|
||||
}},
|
||||
{"Version", version_}};
|
||||
|
||||
if (pt_ == provider_type::encrypt) {
|
||||
if (prov_ == provider_type::encrypt) {
|
||||
ret.erase("ChunkDownloaderTimeoutSeconds");
|
||||
ret.erase("EnableChunkDownloaderTimeout");
|
||||
ret.erase("EnableMaxCacheSize");
|
||||
@ -229,13 +236,13 @@ auto app_config::get_json() const -> json {
|
||||
ret.erase("RetryReadCount");
|
||||
ret.erase("RingBufferFileSize");
|
||||
ret.erase("S3Config");
|
||||
} else if (pt_ == provider_type::s3) {
|
||||
} else if (prov_ == provider_type::s3) {
|
||||
ret.erase("EncryptConfig");
|
||||
ret.erase("HostConfig");
|
||||
} else if (pt_ == provider_type::sia) {
|
||||
} else if (prov_ == provider_type::sia) {
|
||||
ret.erase("EncryptConfig");
|
||||
ret.erase("S3Config");
|
||||
} else if (pt_ == provider_type::remote) {
|
||||
} else if (prov_ == provider_type::remote) {
|
||||
ret.erase("ChunkDownloaderTimeoutSeconds");
|
||||
ret.erase("EnableChunkDownloaderTimeout");
|
||||
ret.erase("EnableChunkDownloaderTimeout");
|
||||
@ -261,50 +268,56 @@ auto app_config::get_json() const -> json {
|
||||
|
||||
auto app_config::get_max_cache_size_bytes() const -> std::uint64_t {
|
||||
const auto max_space =
|
||||
std::max(static_cast<std::uint64_t>(100ull * 1024ull * 1024ull),
|
||||
std::max(static_cast<std::uint64_t>(100ULL * 1024ULL * 1024ULL),
|
||||
max_cache_size_bytes_);
|
||||
return std::min(utils::file::get_free_drive_space(get_cache_directory()),
|
||||
max_space);
|
||||
}
|
||||
|
||||
auto app_config::get_provider_api_password(const provider_type &pt)
|
||||
auto app_config::get_provider_api_password(const provider_type &prov)
|
||||
-> std::string {
|
||||
#ifdef _WIN32
|
||||
auto api_file =
|
||||
utils::path::combine(utils::get_local_app_data_directory(),
|
||||
{get_provider_display_name(pt), "apipassword"});
|
||||
{get_provider_display_name(prov), "apipassword"});
|
||||
#else
|
||||
#ifdef __APPLE__
|
||||
auto api_file =
|
||||
utils::path::combine(utils::path::resolve("~"),
|
||||
{"/Library/Application Support",
|
||||
get_provider_display_name(pt), "apipassword"});
|
||||
get_provider_display_name(prov), "apipassword"});
|
||||
#else
|
||||
auto api_file = utils::path::combine(utils::path::resolve("~/."),
|
||||
{get_provider_name(pt), "apipassword"});
|
||||
auto api_file = utils::path::combine(
|
||||
utils::path::resolve("~/."), {get_provider_name(prov), "apipassword"});
|
||||
#endif
|
||||
#endif
|
||||
auto lines = utils::file::read_file_lines(api_file);
|
||||
return lines.empty() ? "" : utils::string::trim(lines[0]);
|
||||
}
|
||||
|
||||
auto app_config::get_provider_display_name(const provider_type &pt)
|
||||
auto app_config::get_provider_display_name(const provider_type &prov)
|
||||
-> std::string {
|
||||
static const std::array<std::string,
|
||||
static_cast<std::size_t>(provider_type::unknown)>
|
||||
PROVIDER_DISPLAY_NAMES = {
|
||||
"Sia", "Remote", "S3", "Passthrough", "Encrypt",
|
||||
"Sia",
|
||||
"Remote",
|
||||
"S3",
|
||||
"Encrypt",
|
||||
};
|
||||
return PROVIDER_DISPLAY_NAMES[static_cast<std::size_t>(pt)];
|
||||
return PROVIDER_DISPLAY_NAMES[static_cast<std::size_t>(prov)];
|
||||
}
|
||||
|
||||
auto app_config::get_provider_name(const provider_type &pt) -> std::string {
|
||||
auto app_config::get_provider_name(const provider_type &prov) -> std::string {
|
||||
static const std::array<std::string,
|
||||
static_cast<std::size_t>(provider_type::unknown)>
|
||||
PROVIDER_NAMES = {
|
||||
"sia", "remote", "s3", "passthrough", "encrypt",
|
||||
"sia",
|
||||
"remote",
|
||||
"s3",
|
||||
"encrypt",
|
||||
};
|
||||
return PROVIDER_NAMES[static_cast<std::size_t>(pt)];
|
||||
return PROVIDER_NAMES[static_cast<std::size_t>(prov)];
|
||||
}
|
||||
|
||||
auto app_config::get_value_by_name(const std::string &name) -> std::string {
|
||||
@ -447,8 +460,11 @@ auto app_config::get_value_by_name(const std::string &name) -> std::string {
|
||||
if (name == "S3Config.URL") {
|
||||
return s3_config_.url;
|
||||
}
|
||||
if (name == "S3Config.UsePathStyle") {
|
||||
return utils::string::from_bool(s3_config_.use_path_style);
|
||||
}
|
||||
if (name == "S3Config.UseRegionInURL") {
|
||||
return std::to_string(s3_config_.use_region_in_url);
|
||||
return utils::string::from_bool(s3_config_.use_region_in_url);
|
||||
}
|
||||
if (name == "S3Config.TimeoutMs") {
|
||||
return std::to_string(s3_config_.timeout_ms);
|
||||
@ -463,14 +479,14 @@ auto app_config::load() -> bool {
|
||||
auto ret = false;
|
||||
|
||||
const auto config_file_path = get_config_file_path();
|
||||
recur_mutex_lock l(read_write_mutex_);
|
||||
recur_mutex_lock lock(read_write_mutex_);
|
||||
if (utils::file::is_file(config_file_path)) {
|
||||
try {
|
||||
std::ifstream config_file(&config_file_path[0]);
|
||||
std::ifstream config_file(config_file_path.data());
|
||||
if (config_file.is_open()) {
|
||||
std::stringstream ss;
|
||||
ss << config_file.rdbuf();
|
||||
const auto json_text = ss.str();
|
||||
std::stringstream stream;
|
||||
stream << config_file.rdbuf();
|
||||
const auto json_text = stream.str();
|
||||
config_file.close();
|
||||
if ((ret = not json_text.empty())) {
|
||||
const auto json_document = json::parse(json_text);
|
||||
@ -510,20 +526,20 @@ auto app_config::load() -> bool {
|
||||
|
||||
if (json_document.find("HostConfig") != json_document.end()) {
|
||||
auto host_config_json = json_document["HostConfig"];
|
||||
auto hc = hc_;
|
||||
get_value(host_config_json, "AgentString", hc.agent_string, ret);
|
||||
get_value(host_config_json, "ApiPassword", hc.api_password, ret);
|
||||
get_value(host_config_json, "ApiPort", hc.api_port, ret);
|
||||
get_value(host_config_json, "HostNameOrIp", hc.host_name_or_ip,
|
||||
auto cfg = hc_;
|
||||
get_value(host_config_json, "AgentString", cfg.agent_string, ret);
|
||||
get_value(host_config_json, "ApiPassword", cfg.api_password, ret);
|
||||
get_value(host_config_json, "ApiPort", cfg.api_port, ret);
|
||||
get_value(host_config_json, "HostNameOrIp", cfg.host_name_or_ip,
|
||||
ret);
|
||||
get_value(host_config_json, "TimeoutMs", hc.timeout_ms, ret);
|
||||
hc_ = hc;
|
||||
get_value(host_config_json, "TimeoutMs", cfg.timeout_ms, ret);
|
||||
hc_ = cfg;
|
||||
} else {
|
||||
ret = false;
|
||||
}
|
||||
|
||||
if (hc_.api_password.empty()) {
|
||||
hc_.api_password = get_provider_api_password(pt_);
|
||||
hc_.api_password = get_provider_api_password(prov_);
|
||||
if (hc_.api_password.empty()) {
|
||||
ret = false;
|
||||
}
|
||||
@ -531,20 +547,22 @@ auto app_config::load() -> bool {
|
||||
|
||||
if (json_document.find("S3Config") != json_document.end()) {
|
||||
auto s3_config_json = json_document["S3Config"];
|
||||
auto s3 = s3_config_;
|
||||
get_value(s3_config_json, "AccessKey", s3.access_key, ret);
|
||||
get_value(s3_config_json, "Bucket", s3.bucket, ret);
|
||||
auto s3_cfg = s3_config_;
|
||||
get_value(s3_config_json, "AccessKey", s3_cfg.access_key, ret);
|
||||
get_value(s3_config_json, "Bucket", s3_cfg.bucket, ret);
|
||||
get_value(s3_config_json, "CacheTimeoutSeconds",
|
||||
s3.cache_timeout_secs, ret);
|
||||
get_value(s3_config_json, "EncryptionToken", s3.encryption_token,
|
||||
s3_cfg.cache_timeout_secs, ret);
|
||||
get_value(s3_config_json, "EncryptionToken",
|
||||
s3_cfg.encryption_token, ret);
|
||||
get_value(s3_config_json, "Region", s3_cfg.region, ret);
|
||||
get_value(s3_config_json, "SecretKey", s3_cfg.secret_key, ret);
|
||||
get_value(s3_config_json, "TimeoutMs", s3_cfg.timeout_ms, ret);
|
||||
get_value(s3_config_json, "URL", s3_cfg.url, ret);
|
||||
get_value(s3_config_json, "UsePathStyle", s3_cfg.use_path_style,
|
||||
ret);
|
||||
get_value(s3_config_json, "Region", s3.region, ret);
|
||||
get_value(s3_config_json, "SecretKey", s3.secret_key, ret);
|
||||
get_value(s3_config_json, "TimeoutMs", s3.timeout_ms, ret);
|
||||
get_value(s3_config_json, "URL", s3.url, ret);
|
||||
get_value(s3_config_json, "UseRegionInURL", s3.use_region_in_url,
|
||||
ret);
|
||||
s3_config_ = s3;
|
||||
get_value(s3_config_json, "UseRegionInURL",
|
||||
s3_cfg.use_region_in_url, ret);
|
||||
s3_config_ = s3_cfg;
|
||||
} else {
|
||||
ret = false;
|
||||
}
|
||||
@ -593,13 +611,13 @@ auto app_config::load() -> bool {
|
||||
ret = false;
|
||||
}
|
||||
|
||||
std::uint64_t version = 0u;
|
||||
std::uint64_t version{};
|
||||
get_value(json_document, "Version", version, ret);
|
||||
|
||||
// Handle configuration defaults for new config versions
|
||||
if (version != REPERTORY_CONFIG_VERSION) {
|
||||
if (version > REPERTORY_CONFIG_VERSION) {
|
||||
version = 0u;
|
||||
version = 0U;
|
||||
}
|
||||
|
||||
version_ = version;
|
||||
@ -622,7 +640,7 @@ auto app_config::load() -> bool {
|
||||
|
||||
void app_config::save() {
|
||||
const auto configFilePath = get_config_file_path();
|
||||
recur_mutex_lock l(read_write_mutex_);
|
||||
recur_mutex_lock lock(read_write_mutex_);
|
||||
if (config_changed_ || not utils::file::is_file(configFilePath)) {
|
||||
if (not utils::file::is_directory(data_directory_)) {
|
||||
if (not utils::file::create_full_directory_path(data_directory_)) {
|
||||
@ -684,19 +702,19 @@ auto app_config::set_value_by_name(const std::string &name,
|
||||
}
|
||||
if (name == "EnableChunkDownloaderTimeout") {
|
||||
set_enable_chunk_downloader_timeout(utils::string::to_bool(value));
|
||||
return std::to_string(get_enable_chunk_download_timeout());
|
||||
return utils::string::from_bool(get_enable_chunk_download_timeout());
|
||||
}
|
||||
if (name == "EnableCommDurationEvents") {
|
||||
set_enable_comm_duration_events(utils::string::to_bool(value));
|
||||
return std::to_string(get_enable_comm_duration_events());
|
||||
return utils::string::from_bool(get_enable_comm_duration_events());
|
||||
}
|
||||
if (name == "EnableDriveEvents") {
|
||||
set_enable_drive_events(utils::string::to_bool(value));
|
||||
return std::to_string(get_enable_drive_events());
|
||||
return utils::string::from_bool(get_enable_drive_events());
|
||||
}
|
||||
if (name == "EnableMaxCacheSize") {
|
||||
set_enable_max_cache_size(utils::string::to_bool(value));
|
||||
return std::to_string(get_enable_max_cache_size());
|
||||
return utils::string::from_bool(get_enable_max_cache_size());
|
||||
#ifdef _WIN32
|
||||
}
|
||||
if (name == "EnableMountManager") {
|
||||
@ -722,7 +740,7 @@ auto app_config::set_value_by_name(const std::string &name,
|
||||
}
|
||||
if (name == "EvictionUsesAccessedTime") {
|
||||
set_eviction_uses_accessed_time(utils::string::to_bool(value));
|
||||
return std::to_string(get_eviction_uses_accessed_time());
|
||||
return utils::string::from_bool(get_eviction_uses_accessed_time());
|
||||
}
|
||||
if (name == "HighFreqIntervalSeconds") {
|
||||
set_high_frequency_interval_secs(utils::string::to_uint8(value));
|
||||
@ -779,11 +797,11 @@ auto app_config::set_value_by_name(const std::string &name,
|
||||
}
|
||||
if (name == "RemoteMount.EnableRemoteMount") {
|
||||
set_enable_remote_mount(utils::string::to_bool(value));
|
||||
return std::to_string(get_enable_remote_mount());
|
||||
return utils::string::from_bool(get_enable_remote_mount());
|
||||
}
|
||||
if (name == "RemoteMount.IsRemoteMount") {
|
||||
set_is_remote_mount(utils::string::to_bool(value));
|
||||
return std::to_string(get_is_remote_mount());
|
||||
return utils::string::from_bool(get_is_remote_mount());
|
||||
}
|
||||
if (name == "RemoteMount.RemoteClientPoolSize") {
|
||||
set_remote_client_pool_size(utils::string::to_uint8(value));
|
||||
@ -831,7 +849,7 @@ auto app_config::set_value_by_name(const std::string &name,
|
||||
}
|
||||
if (name == "S3Config.CacheTimeoutSeconds") {
|
||||
const auto timeout =
|
||||
std::max(std::uint16_t(5u), utils::string::to_uint16(value));
|
||||
std::max(std::uint16_t(5U), utils::string::to_uint16(value));
|
||||
set_value(s3_config_.cache_timeout_secs, timeout);
|
||||
return std::to_string(s3_config_.cache_timeout_secs);
|
||||
}
|
||||
@ -847,9 +865,13 @@ auto app_config::set_value_by_name(const std::string &name,
|
||||
set_value(s3_config_.url, value);
|
||||
return s3_config_.url;
|
||||
}
|
||||
if (name == "S3Config.UsePathStyle") {
|
||||
set_value(s3_config_.use_path_style, utils::string::to_bool(value));
|
||||
return utils::string::from_bool(s3_config_.use_path_style);
|
||||
}
|
||||
if (name == "S3Config.UseRegionInURL") {
|
||||
set_value(s3_config_.use_region_in_url, utils::string::to_bool(value));
|
||||
return std::to_string(s3_config_.use_region_in_url);
|
||||
return utils::string::from_bool(s3_config_.use_region_in_url);
|
||||
}
|
||||
if (name == "S3Config.TimeoutMs") {
|
||||
set_value(s3_config_.timeout_ms, utils::string::to_uint32(value));
|
||||
|
@ -43,32 +43,36 @@ const curl_comm::write_callback curl_comm::write_headers =
|
||||
auto &headers = *reinterpret_cast<http_headers *>(outstream);
|
||||
const auto header = std::string(buffer, size * nitems);
|
||||
const auto parts = utils::string::split(header, ':');
|
||||
if (parts.size() > 1u) {
|
||||
auto data = header.substr(parts[0u].size() + 1u);
|
||||
if (parts.size() > 1U) {
|
||||
auto data = header.substr(parts[0U].size() + 1U);
|
||||
utils::string::left_trim(data);
|
||||
utils::string::right_trim(data, '\r');
|
||||
utils::string::right_trim(data, '\n');
|
||||
utils::string::right_trim(data, '\r');
|
||||
headers[utils::string::to_lower(parts[0u])] = data;
|
||||
headers[utils::string::to_lower(parts[0U])] = data;
|
||||
}
|
||||
return size * nitems;
|
||||
});
|
||||
|
||||
curl_comm::curl_comm(host_config hc)
|
||||
: host_config_(std::move(hc)), s3_config_(std::nullopt) {}
|
||||
curl_comm::curl_comm(host_config cfg)
|
||||
: host_config_(std::move(cfg)), s3_config_(std::nullopt) {}
|
||||
|
||||
curl_comm::curl_comm(s3_config s3)
|
||||
: host_config_(std::nullopt), s3_config_(std::move(s3)) {}
|
||||
curl_comm::curl_comm(s3_config cfg)
|
||||
: host_config_(std::nullopt), s3_config_(std::move(cfg)) {}
|
||||
|
||||
auto curl_comm::construct_url(CURL *curl, const std::string &relative_path,
|
||||
const host_config &hc) -> std::string {
|
||||
auto custom_port =
|
||||
(((hc.protocol == "http") && (hc.api_port == 80U || hc.api_port == 0U)) ||
|
||||
((hc.protocol == "https") && (hc.api_port == 443U || hc.api_port == 0U)))
|
||||
? ""
|
||||
: ":" + std::to_string(hc.api_port);
|
||||
auto url = hc.protocol + "://" +
|
||||
utils::string::trim_copy(hc.host_name_or_ip) + custom_port;
|
||||
const host_config &cfg) -> std::string {
|
||||
static constexpr const auto http = 80U;
|
||||
static constexpr const auto https = 443U;
|
||||
|
||||
auto custom_port = (((cfg.protocol == "http") &&
|
||||
(cfg.api_port == http || cfg.api_port == 0U)) ||
|
||||
((cfg.protocol == "https") &&
|
||||
(cfg.api_port == https || cfg.api_port == 0U)))
|
||||
? ""
|
||||
: ":" + std::to_string(cfg.api_port);
|
||||
auto url = cfg.protocol + "://" +
|
||||
utils::string::trim_copy(cfg.host_name_or_ip) + custom_port;
|
||||
|
||||
static const auto complete_url = [](const std::string ¤t_path,
|
||||
const std::string &parent_path,
|
||||
@ -80,40 +84,40 @@ auto curl_comm::construct_url(CURL *curl, const std::string &relative_path,
|
||||
return final_url;
|
||||
};
|
||||
|
||||
auto path = utils::path::combine("/", {hc.path});
|
||||
auto path = utils::path::combine("/", {cfg.path});
|
||||
return relative_path.empty()
|
||||
? complete_url(path, hc.path, url)
|
||||
? complete_url(path, cfg.path, url)
|
||||
: complete_url(utils::path::combine(
|
||||
path, {url_encode(curl, relative_path, true)}),
|
||||
relative_path, url);
|
||||
}
|
||||
|
||||
auto curl_comm::create_host_config(const s3_config &config,
|
||||
bool use_s3_path_style) -> host_config {
|
||||
host_config hc{};
|
||||
hc.api_password = config.secret_key;
|
||||
hc.api_user = config.access_key;
|
||||
auto curl_comm::create_host_config(const s3_config &cfg, bool use_s3_path_style)
|
||||
-> host_config {
|
||||
host_config host_cfg{};
|
||||
host_cfg.api_password = cfg.secret_key;
|
||||
host_cfg.api_user = cfg.access_key;
|
||||
|
||||
auto pos = config.url.find(':');
|
||||
hc.host_name_or_ip = config.url.substr(pos + 3U);
|
||||
if (config.use_region_in_url && not config.region.empty()) {
|
||||
auto parts = utils::string::split(hc.host_name_or_ip, '.', false);
|
||||
auto pos = cfg.url.find(':');
|
||||
host_cfg.host_name_or_ip = cfg.url.substr(pos + 3U);
|
||||
if (cfg.use_region_in_url && not cfg.region.empty()) {
|
||||
auto parts = utils::string::split(host_cfg.host_name_or_ip, '.', false);
|
||||
if (parts.size() > 1U) {
|
||||
parts.insert(parts.begin() + 1U, config.region);
|
||||
hc.host_name_or_ip = utils::string::join(parts, '.');
|
||||
parts.insert(parts.begin() + 1U, cfg.region);
|
||||
host_cfg.host_name_or_ip = utils::string::join(parts, '.');
|
||||
}
|
||||
}
|
||||
|
||||
if (not use_s3_path_style) {
|
||||
hc.host_name_or_ip = config.bucket + '.' + hc.host_name_or_ip;
|
||||
host_cfg.host_name_or_ip = cfg.bucket + '.' + host_cfg.host_name_or_ip;
|
||||
}
|
||||
|
||||
hc.protocol = config.url.substr(0U, pos);
|
||||
host_cfg.protocol = cfg.url.substr(0U, pos);
|
||||
if (use_s3_path_style) {
|
||||
hc.path = '/' + config.bucket;
|
||||
host_cfg.path = '/' + cfg.bucket;
|
||||
}
|
||||
|
||||
return hc;
|
||||
return host_cfg;
|
||||
}
|
||||
|
||||
void curl_comm::enable_s3_path_style(bool enable) {
|
||||
@ -126,7 +130,7 @@ auto curl_comm::make_request(const curl::requests::http_delete &del,
|
||||
return make_request(
|
||||
s3_config_.has_value()
|
||||
? create_host_config(s3_config_.value(), use_s3_path_style_)
|
||||
: host_config_.value(),
|
||||
: host_config_.value_or(host_config{}),
|
||||
del, response_code, stop_requested);
|
||||
}
|
||||
|
||||
@ -136,7 +140,7 @@ auto curl_comm::make_request(const curl::requests::http_get &get,
|
||||
return make_request(
|
||||
s3_config_.has_value()
|
||||
? create_host_config(s3_config_.value(), use_s3_path_style_)
|
||||
: host_config_.value(),
|
||||
: host_config_.value_or(host_config{}),
|
||||
get, response_code, stop_requested);
|
||||
}
|
||||
|
||||
@ -146,7 +150,7 @@ auto curl_comm::make_request(const curl::requests::http_head &head,
|
||||
return make_request(
|
||||
s3_config_.has_value()
|
||||
? create_host_config(s3_config_.value(), use_s3_path_style_)
|
||||
: host_config_.value(),
|
||||
: host_config_.value_or(host_config{}),
|
||||
head, response_code, stop_requested);
|
||||
}
|
||||
|
||||
@ -156,7 +160,7 @@ auto curl_comm::make_request(const curl::requests::http_put_file &put_file,
|
||||
return make_request(
|
||||
s3_config_.has_value()
|
||||
? create_host_config(s3_config_.value(), use_s3_path_style_)
|
||||
: host_config_.value(),
|
||||
: host_config_.value_or(host_config{}),
|
||||
put_file, response_code, stop_requested);
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,8 @@ multi_request::~multi_request() {
|
||||
}
|
||||
|
||||
void multi_request::get_result(CURLcode &curl_code, long &http_code) {
|
||||
static constexpr const auto timeout_ms = 100;
|
||||
|
||||
curl_code = CURLcode::CURLE_ABORTED_BY_CALLBACK;
|
||||
http_code = -1;
|
||||
|
||||
@ -45,8 +47,8 @@ void multi_request::get_result(CURLcode &curl_code, long &http_code) {
|
||||
int running_handles = 0;
|
||||
curl_multi_perform(multi_handle_, &running_handles);
|
||||
while (not error && (running_handles > 0) && not stop_requested_) {
|
||||
int ignored;
|
||||
curl_multi_wait(multi_handle_, nullptr, 0, 100, &ignored);
|
||||
int ignored{};
|
||||
curl_multi_wait(multi_handle_, nullptr, 0, timeout_ms, &ignored);
|
||||
|
||||
const auto ret = curl_multi_perform(multi_handle_, &running_handles);
|
||||
error = (ret != CURLM_CALL_MULTI_PERFORM) && (ret != CURLM_OK);
|
||||
@ -56,7 +58,7 @@ void multi_request::get_result(CURLcode &curl_code, long &http_code) {
|
||||
int remaining_messages = 0;
|
||||
auto *multi_result =
|
||||
curl_multi_info_read(multi_handle_, &remaining_messages);
|
||||
if (multi_result && (multi_result->msg == CURLMSG_DONE)) {
|
||||
if ((multi_result != nullptr) && (multi_result->msg == CURLMSG_DONE)) {
|
||||
curl_easy_getinfo(multi_result->easy_handle, CURLINFO_RESPONSE_CODE,
|
||||
&http_code);
|
||||
curl_code = multi_result->data.result;
|
||||
|
@ -24,57 +24,46 @@
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
namespace repertory::curl::requests {
|
||||
auto http_put_file::get_path() const -> std::string {
|
||||
if (reader) {
|
||||
auto updated_path = path;
|
||||
return utils::string::replace(updated_path, file_name,
|
||||
reader->get_encrypted_file_name());
|
||||
}
|
||||
|
||||
return http_request_base::get_path();
|
||||
}
|
||||
|
||||
auto http_put_file::set_method(CURL *curl, stop_type &stop_requested) const
|
||||
-> bool {
|
||||
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
|
||||
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
|
||||
|
||||
if (not source_path.empty()) {
|
||||
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
|
||||
if (not encryption_token.value_or("").empty()) {
|
||||
if (not reader) {
|
||||
reader = std::make_shared<utils::encryption::encrypting_reader>(
|
||||
file_name, source_path, stop_requested, encryption_token.value());
|
||||
}
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA, reader.get());
|
||||
curl_easy_setopt(
|
||||
curl, CURLOPT_READFUNCTION,
|
||||
static_cast<curl_read_callback>(
|
||||
utils::encryption::encrypting_reader::reader_function));
|
||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE,
|
||||
reader->get_total_size());
|
||||
return true;
|
||||
}
|
||||
|
||||
read_info = std::make_shared<read_file_info>(read_file_info{
|
||||
stop_requested,
|
||||
});
|
||||
|
||||
if (native_file::open(source_path, read_info->nf) != api_error::success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
read_info->nf->set_auto_close(true);
|
||||
|
||||
std::uint64_t file_size{};
|
||||
if (not read_info->nf->get_file_size(file_size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA, read_info.get());
|
||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_file_data);
|
||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, file_size);
|
||||
if (source_path.empty()) {
|
||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, 0L);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (reader) {
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA, reader.get());
|
||||
curl_easy_setopt(
|
||||
curl, CURLOPT_READFUNCTION,
|
||||
static_cast<curl_read_callback>(
|
||||
utils::encryption::encrypting_reader::reader_function));
|
||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, reader->get_total_size());
|
||||
return true;
|
||||
}
|
||||
|
||||
read_info = std::make_shared<read_file_info>(read_file_info{
|
||||
stop_requested,
|
||||
});
|
||||
|
||||
if (native_file::create_or_open(source_path, read_info->nf) !=
|
||||
api_error::success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
read_info->nf->set_auto_close(true);
|
||||
|
||||
std::uint64_t file_size{};
|
||||
if (not read_info->nf->get_file_size(file_size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA, read_info.get());
|
||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_file_data);
|
||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, file_size);
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace repertory::curl::requests
|
||||
|
@ -30,23 +30,23 @@ void client_pool::pool::execute(
|
||||
std::uint64_t thread_id, const worker_callback &worker,
|
||||
const worker_complete_callback &worker_complete) {
|
||||
const auto index = thread_id % pool_queues_.size();
|
||||
auto wi = std::make_shared<work_item>(worker, worker_complete);
|
||||
auto job = std::make_shared<work_item>(worker, worker_complete);
|
||||
auto &pool_queue = pool_queues_[index];
|
||||
|
||||
unique_mutex_lock queue_lock(pool_queue->mutex);
|
||||
pool_queue->queue.emplace_back(wi);
|
||||
pool_queue->queue.emplace_back(job);
|
||||
pool_queue->notify.notify_all();
|
||||
queue_lock.unlock();
|
||||
}
|
||||
|
||||
client_pool::pool::pool(std::uint8_t pool_size) {
|
||||
event_system::instance().raise<service_started>("client_pool");
|
||||
thread_index_ = 0u;
|
||||
for (std::uint8_t i = 0u; i < pool_size; i++) {
|
||||
|
||||
for (std::uint8_t i = 0U; i < pool_size; i++) {
|
||||
pool_queues_.emplace_back(std::make_unique<work_queue>());
|
||||
}
|
||||
|
||||
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]() {
|
||||
const auto thread_index = thread_index_++;
|
||||
|
||||
@ -88,12 +88,12 @@ client_pool::pool::pool(std::uint8_t pool_size) {
|
||||
|
||||
queue_lock.lock();
|
||||
while (not queue.empty()) {
|
||||
auto wi = queue.front();
|
||||
auto job = queue.front();
|
||||
queue.pop_front();
|
||||
queue_notify.notify_all();
|
||||
queue_lock.unlock();
|
||||
|
||||
wi->work_complete(utils::from_api_error(api_error::download_stopped));
|
||||
job->work_complete(utils::from_api_error(api_error::download_stopped));
|
||||
|
||||
queue_lock.lock();
|
||||
}
|
||||
@ -108,7 +108,7 @@ void client_pool::pool::shutdown() {
|
||||
shutdown_ = true;
|
||||
|
||||
for (auto &pool_queue : pool_queues_) {
|
||||
unique_mutex_lock l(pool_queue->mutex);
|
||||
mutex_lock lock(pool_queue->mutex);
|
||||
pool_queue->notify.notify_all();
|
||||
}
|
||||
|
||||
@ -148,8 +148,8 @@ void client_pool::shutdown() {
|
||||
unique_mutex_lock pool_lock(pool_mutex_);
|
||||
if (not shutdown_) {
|
||||
shutdown_ = true;
|
||||
for (auto &kv : pool_lookup_) {
|
||||
kv.second->shutdown();
|
||||
for (auto &pool_entry : pool_lookup_) {
|
||||
pool_entry.second->shutdown();
|
||||
}
|
||||
pool_lookup_.clear();
|
||||
}
|
||||
|
@ -32,7 +32,7 @@
|
||||
namespace repertory {
|
||||
void packet::clear() {
|
||||
buffer_.clear();
|
||||
decode_offset_ = 0u;
|
||||
decode_offset_ = 0U;
|
||||
}
|
||||
|
||||
auto packet::decode(std::string &data) -> packet::error_type {
|
||||
@ -59,7 +59,7 @@ auto packet::decode(void *&ptr) -> packet::error_type {
|
||||
}
|
||||
|
||||
auto packet::decode(void *buffer, std::size_t size) -> packet::error_type {
|
||||
if (size) {
|
||||
if (size != 0U) {
|
||||
const auto read_size =
|
||||
utils::calculate_read_size(buffer_.size(), size, decode_offset_);
|
||||
if (read_size == size) {
|
||||
@ -75,153 +75,153 @@ auto packet::decode(void *buffer, std::size_t size) -> packet::error_type {
|
||||
return utils::from_api_error(api_error::success);
|
||||
}
|
||||
|
||||
auto packet::decode(std::int8_t &i) -> packet::error_type {
|
||||
const auto ret = decode(&i, sizeof(i));
|
||||
auto packet::decode(std::int8_t &val) -> packet::error_type {
|
||||
const auto ret = decode(&val, sizeof(val));
|
||||
if (ret == 0) {
|
||||
boost::endian::big_to_native_inplace(i);
|
||||
boost::endian::big_to_native_inplace(val);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto packet::decode(std::uint8_t &i) -> packet::error_type {
|
||||
const auto ret = decode(&i, sizeof(i));
|
||||
auto packet::decode(std::uint8_t &val) -> packet::error_type {
|
||||
const auto ret = decode(&val, sizeof(val));
|
||||
if (ret == 0) {
|
||||
boost::endian::big_to_native_inplace(i);
|
||||
boost::endian::big_to_native_inplace(val);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto packet::decode(std::int16_t &i) -> packet::error_type {
|
||||
const auto ret = decode(&i, sizeof(i));
|
||||
auto packet::decode(std::int16_t &val) -> packet::error_type {
|
||||
const auto ret = decode(&val, sizeof(val));
|
||||
if (ret == 0) {
|
||||
boost::endian::big_to_native_inplace(i);
|
||||
boost::endian::big_to_native_inplace(val);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto packet::decode(std::uint16_t &i) -> packet::error_type {
|
||||
const auto ret = decode(&i, sizeof(i));
|
||||
auto packet::decode(std::uint16_t &val) -> packet::error_type {
|
||||
const auto ret = decode(&val, sizeof(val));
|
||||
if (ret == 0) {
|
||||
boost::endian::big_to_native_inplace(i);
|
||||
boost::endian::big_to_native_inplace(val);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto packet::decode(std::int32_t &i) -> packet::error_type {
|
||||
const auto ret = decode(&i, sizeof(i));
|
||||
auto packet::decode(std::int32_t &val) -> packet::error_type {
|
||||
const auto ret = decode(&val, sizeof(val));
|
||||
if (ret == 0) {
|
||||
boost::endian::big_to_native_inplace(i);
|
||||
boost::endian::big_to_native_inplace(val);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto packet::decode(std::uint32_t &i) -> packet::error_type {
|
||||
const auto ret = decode(&i, sizeof(i));
|
||||
auto packet::decode(std::uint32_t &val) -> packet::error_type {
|
||||
const auto ret = decode(&val, sizeof(val));
|
||||
if (ret == 0) {
|
||||
boost::endian::big_to_native_inplace(i);
|
||||
boost::endian::big_to_native_inplace(val);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto packet::decode(std::int64_t &i) -> packet::error_type {
|
||||
const auto ret = decode(&i, sizeof(i));
|
||||
auto packet::decode(std::int64_t &val) -> packet::error_type {
|
||||
const auto ret = decode(&val, sizeof(val));
|
||||
if (ret == 0) {
|
||||
boost::endian::big_to_native_inplace(i);
|
||||
boost::endian::big_to_native_inplace(val);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto packet::decode(std::uint64_t &i) -> packet::error_type {
|
||||
const auto ret = decode(&i, sizeof(i));
|
||||
auto packet::decode(std::uint64_t &val) -> packet::error_type {
|
||||
const auto ret = decode(&val, sizeof(val));
|
||||
if (ret == 0) {
|
||||
boost::endian::big_to_native_inplace(i);
|
||||
boost::endian::big_to_native_inplace(val);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto packet::decode(remote::setattr_x &i) -> packet::error_type {
|
||||
const auto ret = decode(&i, sizeof(i));
|
||||
auto packet::decode(remote::setattr_x &val) -> packet::error_type {
|
||||
const auto ret = decode(&val, sizeof(val));
|
||||
if (ret == 0) {
|
||||
boost::endian::big_to_native_inplace(i.acctime);
|
||||
boost::endian::big_to_native_inplace(i.bkuptime);
|
||||
boost::endian::big_to_native_inplace(i.chgtime);
|
||||
boost::endian::big_to_native_inplace(i.crtime);
|
||||
boost::endian::big_to_native_inplace(i.flags);
|
||||
boost::endian::big_to_native_inplace(i.gid);
|
||||
boost::endian::big_to_native_inplace(i.mode);
|
||||
boost::endian::big_to_native_inplace(i.modtime);
|
||||
boost::endian::big_to_native_inplace(i.size);
|
||||
boost::endian::big_to_native_inplace(i.uid);
|
||||
boost::endian::big_to_native_inplace(i.valid);
|
||||
boost::endian::big_to_native_inplace(val.acctime);
|
||||
boost::endian::big_to_native_inplace(val.bkuptime);
|
||||
boost::endian::big_to_native_inplace(val.chgtime);
|
||||
boost::endian::big_to_native_inplace(val.crtime);
|
||||
boost::endian::big_to_native_inplace(val.flags);
|
||||
boost::endian::big_to_native_inplace(val.gid);
|
||||
boost::endian::big_to_native_inplace(val.mode);
|
||||
boost::endian::big_to_native_inplace(val.modtime);
|
||||
boost::endian::big_to_native_inplace(val.size);
|
||||
boost::endian::big_to_native_inplace(val.uid);
|
||||
boost::endian::big_to_native_inplace(val.valid);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto packet::decode(remote::stat &i) -> packet::error_type {
|
||||
const auto ret = decode(&i, sizeof(i));
|
||||
auto packet::decode(remote::stat &val) -> packet::error_type {
|
||||
const auto ret = decode(&val, sizeof(val));
|
||||
if (ret == 0) {
|
||||
boost::endian::big_to_native_inplace(i.st_mode);
|
||||
boost::endian::big_to_native_inplace(i.st_nlink);
|
||||
boost::endian::big_to_native_inplace(i.st_uid);
|
||||
boost::endian::big_to_native_inplace(i.st_gid);
|
||||
boost::endian::big_to_native_inplace(i.st_atimespec);
|
||||
boost::endian::big_to_native_inplace(i.st_mtimespec);
|
||||
boost::endian::big_to_native_inplace(i.st_ctimespec);
|
||||
boost::endian::big_to_native_inplace(i.st_birthtimespec);
|
||||
boost::endian::big_to_native_inplace(i.st_size);
|
||||
boost::endian::big_to_native_inplace(i.st_blocks);
|
||||
boost::endian::big_to_native_inplace(i.st_blksize);
|
||||
boost::endian::big_to_native_inplace(i.st_flags);
|
||||
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_uid);
|
||||
boost::endian::big_to_native_inplace(val.st_gid);
|
||||
boost::endian::big_to_native_inplace(val.st_atimespec);
|
||||
boost::endian::big_to_native_inplace(val.st_mtimespec);
|
||||
boost::endian::big_to_native_inplace(val.st_ctimespec);
|
||||
boost::endian::big_to_native_inplace(val.st_birthtimespec);
|
||||
boost::endian::big_to_native_inplace(val.st_size);
|
||||
boost::endian::big_to_native_inplace(val.st_blocks);
|
||||
boost::endian::big_to_native_inplace(val.st_blksize);
|
||||
boost::endian::big_to_native_inplace(val.st_flags);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto packet::decode(remote::statfs &i) -> packet::error_type {
|
||||
const auto ret = decode(&i, sizeof(i));
|
||||
auto packet::decode(remote::statfs &val) -> packet::error_type {
|
||||
const auto ret = decode(&val, sizeof(val));
|
||||
if (ret == 0) {
|
||||
boost::endian::big_to_native_inplace(i.f_bavail);
|
||||
boost::endian::big_to_native_inplace(i.f_bfree);
|
||||
boost::endian::big_to_native_inplace(i.f_blocks);
|
||||
boost::endian::big_to_native_inplace(i.f_favail);
|
||||
boost::endian::big_to_native_inplace(i.f_ffree);
|
||||
boost::endian::big_to_native_inplace(i.f_files);
|
||||
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_blocks);
|
||||
boost::endian::big_to_native_inplace(val.f_favail);
|
||||
boost::endian::big_to_native_inplace(val.f_ffree);
|
||||
boost::endian::big_to_native_inplace(val.f_files);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto packet::decode(remote::statfs_x &i) -> packet::error_type {
|
||||
auto ret = decode(*dynamic_cast<remote::statfs *>(&i));
|
||||
auto packet::decode(remote::statfs_x &val) -> packet::error_type {
|
||||
auto ret = decode(*dynamic_cast<remote::statfs *>(&val));
|
||||
if (ret == 0) {
|
||||
ret = decode(&i.f_mntfromname[0], 1024);
|
||||
ret = decode(&val.f_mntfromname[0U], sizeof(val.f_mntfromname));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto packet::decode(remote::file_info &i) -> packet::error_type {
|
||||
const auto ret = decode(&i, sizeof(i));
|
||||
auto packet::decode(remote::file_info &val) -> packet::error_type {
|
||||
const auto ret = decode(&val, sizeof(val));
|
||||
if (ret == 0) {
|
||||
boost::endian::big_to_native_inplace(i.AllocationSize);
|
||||
boost::endian::big_to_native_inplace(i.ChangeTime);
|
||||
boost::endian::big_to_native_inplace(i.CreationTime);
|
||||
boost::endian::big_to_native_inplace(i.EaSize);
|
||||
boost::endian::big_to_native_inplace(i.FileAttributes);
|
||||
boost::endian::big_to_native_inplace(i.FileSize);
|
||||
boost::endian::big_to_native_inplace(i.HardLinks);
|
||||
boost::endian::big_to_native_inplace(i.IndexNumber);
|
||||
boost::endian::big_to_native_inplace(i.LastAccessTime);
|
||||
boost::endian::big_to_native_inplace(i.LastWriteTime);
|
||||
boost::endian::big_to_native_inplace(i.ReparseTag);
|
||||
boost::endian::big_to_native_inplace(val.AllocationSize);
|
||||
boost::endian::big_to_native_inplace(val.ChangeTime);
|
||||
boost::endian::big_to_native_inplace(val.CreationTime);
|
||||
boost::endian::big_to_native_inplace(val.EaSize);
|
||||
boost::endian::big_to_native_inplace(val.FileAttributes);
|
||||
boost::endian::big_to_native_inplace(val.FileSize);
|
||||
boost::endian::big_to_native_inplace(val.HardLinks);
|
||||
boost::endian::big_to_native_inplace(val.IndexNumber);
|
||||
boost::endian::big_to_native_inplace(val.LastAccessTime);
|
||||
boost::endian::big_to_native_inplace(val.LastWriteTime);
|
||||
boost::endian::big_to_native_inplace(val.ReparseTag);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto packet::decode_json(packet &response, json &json_data) -> int {
|
||||
int ret = 0;
|
||||
std::string data;
|
||||
if ((ret = response.decode(data)) == 0) {
|
||||
auto ret = response.decode(data);
|
||||
if (ret == 0) {
|
||||
try {
|
||||
json_data = json::parse(data);
|
||||
} catch (const std::exception &e) {
|
||||
@ -253,7 +253,7 @@ auto packet::decrypt(const std::string &token) -> packet::error_type {
|
||||
}
|
||||
|
||||
void packet::encode(const void *buffer, std::size_t size, bool should_reserve) {
|
||||
if (size) {
|
||||
if (size != 0U) {
|
||||
if (should_reserve) {
|
||||
buffer_.reserve(buffer_.size() + size);
|
||||
}
|
||||
@ -263,133 +263,130 @@ void packet::encode(const void *buffer, std::size_t size, bool should_reserve) {
|
||||
}
|
||||
|
||||
void packet::encode(const std::string &str) {
|
||||
const auto len = strnlen(&str[0], str.size());
|
||||
const auto len = strnlen(str.c_str(), str.size());
|
||||
buffer_.reserve(len + 1 + buffer_.size());
|
||||
encode(&str[0], len, false);
|
||||
encode(str.c_str(), len, false);
|
||||
buffer_.emplace_back(0);
|
||||
}
|
||||
|
||||
void packet::encode(wchar_t *str) {
|
||||
encode(utils::string::to_utf8(str ? str : L""));
|
||||
}
|
||||
|
||||
void packet::encode(const wchar_t *str) {
|
||||
encode(utils::string::to_utf8(str ? str : L""));
|
||||
encode(utils::string::to_utf8(str == nullptr ? L"" : str));
|
||||
}
|
||||
|
||||
void packet::encode(const std::wstring &str) {
|
||||
encode(utils::string::to_utf8(str));
|
||||
}
|
||||
|
||||
void packet::encode(std::int8_t i) {
|
||||
boost::endian::native_to_big_inplace(i);
|
||||
encode(&i, sizeof(i), true);
|
||||
void packet::encode(std::int8_t val) {
|
||||
boost::endian::native_to_big_inplace(val);
|
||||
encode(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode(std::uint8_t i) {
|
||||
boost::endian::native_to_big_inplace(i);
|
||||
encode(&i, sizeof(i), true);
|
||||
void packet::encode(std::uint8_t val) {
|
||||
boost::endian::native_to_big_inplace(val);
|
||||
encode(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode(std::int16_t i) {
|
||||
boost::endian::native_to_big_inplace(i);
|
||||
encode(&i, sizeof(i), true);
|
||||
void packet::encode(std::int16_t val) {
|
||||
boost::endian::native_to_big_inplace(val);
|
||||
encode(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode(std::uint16_t i) {
|
||||
boost::endian::native_to_big_inplace(i);
|
||||
encode(&i, sizeof(i), true);
|
||||
void packet::encode(std::uint16_t val) {
|
||||
boost::endian::native_to_big_inplace(val);
|
||||
encode(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode(std::int32_t i) {
|
||||
boost::endian::native_to_big_inplace(i);
|
||||
encode(&i, sizeof(i), true);
|
||||
void packet::encode(std::int32_t val) {
|
||||
boost::endian::native_to_big_inplace(val);
|
||||
encode(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode(std::uint32_t i) {
|
||||
boost::endian::native_to_big_inplace(i);
|
||||
encode(&i, sizeof(i), true);
|
||||
void packet::encode(std::uint32_t val) {
|
||||
boost::endian::native_to_big_inplace(val);
|
||||
encode(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode(std::int64_t i) {
|
||||
boost::endian::native_to_big_inplace(i);
|
||||
encode(&i, sizeof(i), true);
|
||||
void packet::encode(std::int64_t val) {
|
||||
boost::endian::native_to_big_inplace(val);
|
||||
encode(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode(std::uint64_t i) {
|
||||
boost::endian::native_to_big_inplace(i);
|
||||
encode(&i, sizeof(i), true);
|
||||
void packet::encode(std::uint64_t val) {
|
||||
boost::endian::native_to_big_inplace(val);
|
||||
encode(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode(remote::setattr_x i) {
|
||||
boost::endian::native_to_big_inplace(i.acctime);
|
||||
boost::endian::native_to_big_inplace(i.bkuptime);
|
||||
boost::endian::native_to_big_inplace(i.chgtime);
|
||||
boost::endian::native_to_big_inplace(i.crtime);
|
||||
boost::endian::native_to_big_inplace(i.flags);
|
||||
boost::endian::native_to_big_inplace(i.gid);
|
||||
boost::endian::native_to_big_inplace(i.mode);
|
||||
boost::endian::native_to_big_inplace(i.modtime);
|
||||
boost::endian::native_to_big_inplace(i.size);
|
||||
boost::endian::native_to_big_inplace(i.uid);
|
||||
boost::endian::native_to_big_inplace(i.valid);
|
||||
void packet::encode(remote::setattr_x val) {
|
||||
boost::endian::native_to_big_inplace(val.acctime);
|
||||
boost::endian::native_to_big_inplace(val.bkuptime);
|
||||
boost::endian::native_to_big_inplace(val.chgtime);
|
||||
boost::endian::native_to_big_inplace(val.crtime);
|
||||
boost::endian::native_to_big_inplace(val.flags);
|
||||
boost::endian::native_to_big_inplace(val.gid);
|
||||
boost::endian::native_to_big_inplace(val.mode);
|
||||
boost::endian::native_to_big_inplace(val.modtime);
|
||||
boost::endian::native_to_big_inplace(val.size);
|
||||
boost::endian::native_to_big_inplace(val.uid);
|
||||
boost::endian::native_to_big_inplace(val.valid);
|
||||
|
||||
encode(&i, sizeof(i), true);
|
||||
encode(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode(remote::stat i) {
|
||||
boost::endian::native_to_big_inplace(i.st_mode);
|
||||
boost::endian::native_to_big_inplace(i.st_nlink);
|
||||
boost::endian::native_to_big_inplace(i.st_uid);
|
||||
boost::endian::native_to_big_inplace(i.st_gid);
|
||||
boost::endian::native_to_big_inplace(i.st_atimespec);
|
||||
boost::endian::native_to_big_inplace(i.st_mtimespec);
|
||||
boost::endian::native_to_big_inplace(i.st_ctimespec);
|
||||
boost::endian::native_to_big_inplace(i.st_birthtimespec);
|
||||
boost::endian::native_to_big_inplace(i.st_size);
|
||||
boost::endian::native_to_big_inplace(i.st_blocks);
|
||||
boost::endian::native_to_big_inplace(i.st_blksize);
|
||||
boost::endian::native_to_big_inplace(i.st_flags);
|
||||
void packet::encode(remote::stat val) {
|
||||
boost::endian::native_to_big_inplace(val.st_mode);
|
||||
boost::endian::native_to_big_inplace(val.st_nlink);
|
||||
boost::endian::native_to_big_inplace(val.st_uid);
|
||||
boost::endian::native_to_big_inplace(val.st_gid);
|
||||
boost::endian::native_to_big_inplace(val.st_atimespec);
|
||||
boost::endian::native_to_big_inplace(val.st_mtimespec);
|
||||
boost::endian::native_to_big_inplace(val.st_ctimespec);
|
||||
boost::endian::native_to_big_inplace(val.st_birthtimespec);
|
||||
boost::endian::native_to_big_inplace(val.st_size);
|
||||
boost::endian::native_to_big_inplace(val.st_blocks);
|
||||
boost::endian::native_to_big_inplace(val.st_blksize);
|
||||
boost::endian::native_to_big_inplace(val.st_flags);
|
||||
|
||||
encode(&i, sizeof(i), true);
|
||||
encode(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode(remote::statfs i, bool should_reserve) {
|
||||
boost::endian::native_to_big_inplace(i.f_bavail);
|
||||
boost::endian::native_to_big_inplace(i.f_bfree);
|
||||
boost::endian::native_to_big_inplace(i.f_blocks);
|
||||
boost::endian::native_to_big_inplace(i.f_favail);
|
||||
boost::endian::native_to_big_inplace(i.f_ffree);
|
||||
boost::endian::native_to_big_inplace(i.f_files);
|
||||
void packet::encode(remote::statfs val, bool should_reserve) {
|
||||
boost::endian::native_to_big_inplace(val.f_bavail);
|
||||
boost::endian::native_to_big_inplace(val.f_bfree);
|
||||
boost::endian::native_to_big_inplace(val.f_blocks);
|
||||
boost::endian::native_to_big_inplace(val.f_favail);
|
||||
boost::endian::native_to_big_inplace(val.f_ffree);
|
||||
boost::endian::native_to_big_inplace(val.f_files);
|
||||
|
||||
encode(&i, sizeof(remote::statfs), should_reserve);
|
||||
encode(&val, sizeof(remote::statfs), should_reserve);
|
||||
}
|
||||
|
||||
void packet::encode(remote::statfs_x i) {
|
||||
buffer_.reserve(buffer_.size() + sizeof(remote::statfs) + 1024);
|
||||
encode(*dynamic_cast<remote::statfs *>(&i), false);
|
||||
encode(&i.f_mntfromname[0], 1024, false);
|
||||
void packet::encode(remote::statfs_x val) {
|
||||
buffer_.reserve(buffer_.size() + sizeof(remote::statfs) +
|
||||
sizeof(val.f_mntfromname));
|
||||
encode(*dynamic_cast<remote::statfs *>(&val), false);
|
||||
encode(&val.f_mntfromname[0], sizeof(val.f_mntfromname), false);
|
||||
}
|
||||
|
||||
void packet::encode(remote::file_info i) {
|
||||
boost::endian::native_to_big_inplace(i.FileAttributes);
|
||||
boost::endian::native_to_big_inplace(i.ReparseTag);
|
||||
boost::endian::native_to_big_inplace(i.AllocationSize);
|
||||
boost::endian::native_to_big_inplace(i.FileSize);
|
||||
boost::endian::native_to_big_inplace(i.CreationTime);
|
||||
boost::endian::native_to_big_inplace(i.LastAccessTime);
|
||||
boost::endian::native_to_big_inplace(i.LastWriteTime);
|
||||
boost::endian::native_to_big_inplace(i.ChangeTime);
|
||||
boost::endian::native_to_big_inplace(i.IndexNumber);
|
||||
boost::endian::native_to_big_inplace(i.HardLinks);
|
||||
boost::endian::native_to_big_inplace(i.EaSize);
|
||||
void packet::encode(remote::file_info val) {
|
||||
boost::endian::native_to_big_inplace(val.FileAttributes);
|
||||
boost::endian::native_to_big_inplace(val.ReparseTag);
|
||||
boost::endian::native_to_big_inplace(val.AllocationSize);
|
||||
boost::endian::native_to_big_inplace(val.FileSize);
|
||||
boost::endian::native_to_big_inplace(val.CreationTime);
|
||||
boost::endian::native_to_big_inplace(val.LastAccessTime);
|
||||
boost::endian::native_to_big_inplace(val.LastWriteTime);
|
||||
boost::endian::native_to_big_inplace(val.ChangeTime);
|
||||
boost::endian::native_to_big_inplace(val.IndexNumber);
|
||||
boost::endian::native_to_big_inplace(val.HardLinks);
|
||||
boost::endian::native_to_big_inplace(val.EaSize);
|
||||
|
||||
encode(&i, sizeof(i), true);
|
||||
encode(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode_top(const void *buffer, std::size_t size,
|
||||
bool should_reserve) {
|
||||
if (size) {
|
||||
if (size != 0U) {
|
||||
if (should_reserve) {
|
||||
buffer_.reserve(buffer_.size() + size);
|
||||
}
|
||||
@ -401,7 +398,7 @@ void packet::encode_top(const void *buffer, std::size_t size,
|
||||
void packet::encode_top(const std::string &str) {
|
||||
const auto len = strnlen(str.c_str(), str.size());
|
||||
buffer_.reserve(len + 1U + buffer_.size());
|
||||
encode_top(&str[0], len, false);
|
||||
encode_top(str.c_str(), len, false);
|
||||
buffer_.insert(buffer_.begin() + static_cast<std::int32_t>(len), 0);
|
||||
}
|
||||
|
||||
@ -409,110 +406,111 @@ void packet::encode_top(const std::wstring &str) {
|
||||
encode_top(utils::string::to_utf8(str));
|
||||
}
|
||||
|
||||
void packet::encode_top(std::int8_t i) {
|
||||
boost::endian::native_to_big_inplace(i);
|
||||
encode_top(&i, sizeof(i), true);
|
||||
void packet::encode_top(std::int8_t val) {
|
||||
boost::endian::native_to_big_inplace(val);
|
||||
encode_top(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode_top(std::uint8_t i) {
|
||||
boost::endian::native_to_big_inplace(i);
|
||||
encode_top(&i, sizeof(i), true);
|
||||
void packet::encode_top(std::uint8_t val) {
|
||||
boost::endian::native_to_big_inplace(val);
|
||||
encode_top(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode_top(std::int16_t i) {
|
||||
boost::endian::native_to_big_inplace(i);
|
||||
encode_top(&i, sizeof(i), true);
|
||||
void packet::encode_top(std::int16_t val) {
|
||||
boost::endian::native_to_big_inplace(val);
|
||||
encode_top(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode_top(std::uint16_t i) {
|
||||
boost::endian::native_to_big_inplace(i);
|
||||
encode_top(&i, sizeof(i), true);
|
||||
void packet::encode_top(std::uint16_t val) {
|
||||
boost::endian::native_to_big_inplace(val);
|
||||
encode_top(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode_top(std::int32_t i) {
|
||||
boost::endian::native_to_big_inplace(i);
|
||||
encode_top(&i, sizeof(i), true);
|
||||
void packet::encode_top(std::int32_t val) {
|
||||
boost::endian::native_to_big_inplace(val);
|
||||
encode_top(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode_top(std::uint32_t i) {
|
||||
boost::endian::native_to_big_inplace(i);
|
||||
encode_top(&i, sizeof(i), true);
|
||||
void packet::encode_top(std::uint32_t val) {
|
||||
boost::endian::native_to_big_inplace(val);
|
||||
encode_top(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode_top(std::int64_t i) {
|
||||
boost::endian::native_to_big_inplace(i);
|
||||
encode_top(&i, sizeof(i), true);
|
||||
void packet::encode_top(std::int64_t val) {
|
||||
boost::endian::native_to_big_inplace(val);
|
||||
encode_top(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode_top(std::uint64_t i) {
|
||||
boost::endian::native_to_big_inplace(i);
|
||||
encode_top(&i, sizeof(i), true);
|
||||
void packet::encode_top(std::uint64_t val) {
|
||||
boost::endian::native_to_big_inplace(val);
|
||||
encode_top(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode_top(remote::setattr_x i) {
|
||||
boost::endian::native_to_big_inplace(i.acctime);
|
||||
boost::endian::native_to_big_inplace(i.bkuptime);
|
||||
boost::endian::native_to_big_inplace(i.chgtime);
|
||||
boost::endian::native_to_big_inplace(i.crtime);
|
||||
boost::endian::native_to_big_inplace(i.flags);
|
||||
boost::endian::native_to_big_inplace(i.gid);
|
||||
boost::endian::native_to_big_inplace(i.mode);
|
||||
boost::endian::native_to_big_inplace(i.modtime);
|
||||
boost::endian::native_to_big_inplace(i.size);
|
||||
boost::endian::native_to_big_inplace(i.uid);
|
||||
boost::endian::native_to_big_inplace(i.valid);
|
||||
void packet::encode_top(remote::setattr_x val) {
|
||||
boost::endian::native_to_big_inplace(val.acctime);
|
||||
boost::endian::native_to_big_inplace(val.bkuptime);
|
||||
boost::endian::native_to_big_inplace(val.chgtime);
|
||||
boost::endian::native_to_big_inplace(val.crtime);
|
||||
boost::endian::native_to_big_inplace(val.flags);
|
||||
boost::endian::native_to_big_inplace(val.gid);
|
||||
boost::endian::native_to_big_inplace(val.mode);
|
||||
boost::endian::native_to_big_inplace(val.modtime);
|
||||
boost::endian::native_to_big_inplace(val.size);
|
||||
boost::endian::native_to_big_inplace(val.uid);
|
||||
boost::endian::native_to_big_inplace(val.valid);
|
||||
|
||||
encode_top(&i, sizeof(i), true);
|
||||
encode_top(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode_top(remote::stat i) {
|
||||
boost::endian::native_to_big_inplace(i.st_mode);
|
||||
boost::endian::native_to_big_inplace(i.st_nlink);
|
||||
boost::endian::native_to_big_inplace(i.st_uid);
|
||||
boost::endian::native_to_big_inplace(i.st_gid);
|
||||
boost::endian::native_to_big_inplace(i.st_atimespec);
|
||||
boost::endian::native_to_big_inplace(i.st_mtimespec);
|
||||
boost::endian::native_to_big_inplace(i.st_ctimespec);
|
||||
boost::endian::native_to_big_inplace(i.st_birthtimespec);
|
||||
boost::endian::native_to_big_inplace(i.st_size);
|
||||
boost::endian::native_to_big_inplace(i.st_blocks);
|
||||
boost::endian::native_to_big_inplace(i.st_blksize);
|
||||
boost::endian::native_to_big_inplace(i.st_flags);
|
||||
void packet::encode_top(remote::stat val) {
|
||||
boost::endian::native_to_big_inplace(val.st_mode);
|
||||
boost::endian::native_to_big_inplace(val.st_nlink);
|
||||
boost::endian::native_to_big_inplace(val.st_uid);
|
||||
boost::endian::native_to_big_inplace(val.st_gid);
|
||||
boost::endian::native_to_big_inplace(val.st_atimespec);
|
||||
boost::endian::native_to_big_inplace(val.st_mtimespec);
|
||||
boost::endian::native_to_big_inplace(val.st_ctimespec);
|
||||
boost::endian::native_to_big_inplace(val.st_birthtimespec);
|
||||
boost::endian::native_to_big_inplace(val.st_size);
|
||||
boost::endian::native_to_big_inplace(val.st_blocks);
|
||||
boost::endian::native_to_big_inplace(val.st_blksize);
|
||||
boost::endian::native_to_big_inplace(val.st_flags);
|
||||
|
||||
encode_top(&i, sizeof(i), true);
|
||||
encode_top(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encode_top(remote::statfs i, bool should_reserve) {
|
||||
boost::endian::native_to_big_inplace(i.f_bavail);
|
||||
boost::endian::native_to_big_inplace(i.f_bfree);
|
||||
boost::endian::native_to_big_inplace(i.f_blocks);
|
||||
boost::endian::native_to_big_inplace(i.f_favail);
|
||||
boost::endian::native_to_big_inplace(i.f_ffree);
|
||||
boost::endian::native_to_big_inplace(i.f_files);
|
||||
void packet::encode_top(remote::statfs val, bool should_reserve) {
|
||||
boost::endian::native_to_big_inplace(val.f_bavail);
|
||||
boost::endian::native_to_big_inplace(val.f_bfree);
|
||||
boost::endian::native_to_big_inplace(val.f_blocks);
|
||||
boost::endian::native_to_big_inplace(val.f_favail);
|
||||
boost::endian::native_to_big_inplace(val.f_ffree);
|
||||
boost::endian::native_to_big_inplace(val.f_files);
|
||||
|
||||
encode_top(&i, sizeof(remote::statfs), should_reserve);
|
||||
encode_top(&val, sizeof(remote::statfs), should_reserve);
|
||||
}
|
||||
|
||||
void packet::encode_top(remote::statfs_x i) {
|
||||
buffer_.reserve(buffer_.size() + sizeof(remote::statfs) + 1024);
|
||||
encode_top(&i.f_mntfromname[0], 1024, false);
|
||||
encode_top(*dynamic_cast<remote::statfs *>(&i), false);
|
||||
void packet::encode_top(remote::statfs_x val) {
|
||||
buffer_.reserve(buffer_.size() + sizeof(remote::statfs) +
|
||||
sizeof(val.f_mntfromname));
|
||||
encode_top(&val.f_mntfromname[0], sizeof(val.f_mntfromname), false);
|
||||
encode_top(*dynamic_cast<remote::statfs *>(&val), false);
|
||||
}
|
||||
|
||||
void packet::encode_top(remote::file_info i) {
|
||||
boost::endian::native_to_big_inplace(i.FileAttributes);
|
||||
boost::endian::native_to_big_inplace(i.ReparseTag);
|
||||
boost::endian::native_to_big_inplace(i.AllocationSize);
|
||||
boost::endian::native_to_big_inplace(i.FileSize);
|
||||
boost::endian::native_to_big_inplace(i.CreationTime);
|
||||
boost::endian::native_to_big_inplace(i.LastAccessTime);
|
||||
boost::endian::native_to_big_inplace(i.LastWriteTime);
|
||||
boost::endian::native_to_big_inplace(i.ChangeTime);
|
||||
boost::endian::native_to_big_inplace(i.IndexNumber);
|
||||
boost::endian::native_to_big_inplace(i.HardLinks);
|
||||
boost::endian::native_to_big_inplace(i.EaSize);
|
||||
void packet::encode_top(remote::file_info val) {
|
||||
boost::endian::native_to_big_inplace(val.FileAttributes);
|
||||
boost::endian::native_to_big_inplace(val.ReparseTag);
|
||||
boost::endian::native_to_big_inplace(val.AllocationSize);
|
||||
boost::endian::native_to_big_inplace(val.FileSize);
|
||||
boost::endian::native_to_big_inplace(val.CreationTime);
|
||||
boost::endian::native_to_big_inplace(val.LastAccessTime);
|
||||
boost::endian::native_to_big_inplace(val.LastWriteTime);
|
||||
boost::endian::native_to_big_inplace(val.ChangeTime);
|
||||
boost::endian::native_to_big_inplace(val.IndexNumber);
|
||||
boost::endian::native_to_big_inplace(val.HardLinks);
|
||||
boost::endian::native_to_big_inplace(val.EaSize);
|
||||
|
||||
encode_top(&i, sizeof(i), true);
|
||||
encode_top(&val, sizeof(val), true);
|
||||
}
|
||||
|
||||
void packet::encrypt(const std::string &token) {
|
||||
@ -550,19 +548,19 @@ auto packet::operator=(data_buffer &&buffer) noexcept -> packet & {
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto packet::operator=(const packet &p) noexcept -> packet & {
|
||||
if (this != &p) {
|
||||
buffer_ = p.buffer_;
|
||||
decode_offset_ = p.decode_offset_;
|
||||
auto packet::operator=(const packet &pkt) noexcept -> packet & {
|
||||
if (this != &pkt) {
|
||||
buffer_ = pkt.buffer_;
|
||||
decode_offset_ = pkt.decode_offset_;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto packet::operator=(packet &&p) noexcept -> packet & {
|
||||
if (this != &p) {
|
||||
buffer_ = std::move(p.buffer_);
|
||||
decode_offset_ = p.decode_offset_;
|
||||
auto packet::operator=(packet &&pkt) noexcept -> packet & {
|
||||
if (this != &pkt) {
|
||||
buffer_ = std::move(pkt.buffer_);
|
||||
decode_offset_ = pkt.decode_offset_;
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
@ -1,575 +0,0 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#if defined(REPERTORY_ENABLE_S3)
|
||||
|
||||
#include "comm/s3/s3_comm.hpp"
|
||||
|
||||
#include "app_config.hpp"
|
||||
#include "comm/curl/curl_comm.hpp"
|
||||
#include "comm/s3/s3_requests.hpp"
|
||||
#include "events/event_system.hpp"
|
||||
#include "events/events.hpp"
|
||||
#include "providers/i_provider.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "types/s3.hpp"
|
||||
#include "utils/encryption.hpp"
|
||||
#include "utils/error_utils.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
#include "utils/polling.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
static const get_key_callback empty_key = []() { return ""; };
|
||||
|
||||
s3_comm::s3_comm(const app_config &config)
|
||||
: config_(config), s3_config_(config.get_s3_config()) {
|
||||
s3_config_.bucket = utils::string::trim(s3_config_.bucket);
|
||||
|
||||
// TODO make configurable
|
||||
const auto enable_path_style =
|
||||
utils::string::begins_with(s3_config_.url, "http://localhost") ||
|
||||
utils::string::begins_with(s3_config_.url, "https://localhost") ||
|
||||
utils::string::begins_with(s3_config_.url, "http://127.0.0.1") ||
|
||||
utils::string::begins_with(s3_config_.url, "https://127.0.0.1");
|
||||
|
||||
s3_client_ = std::make_unique<curl_comm>(s3_config_);
|
||||
s3_client_->enable_s3_path_style(enable_path_style);
|
||||
|
||||
polling::instance().set_callback(
|
||||
{"s3_directory_cache", polling::frequency::high,
|
||||
[this]() { this->clear_expired_directories(); }});
|
||||
}
|
||||
|
||||
s3_comm::s3_comm(s3_comm &&comm)
|
||||
: config_(std::move(comm.config_)),
|
||||
s3_config_(std::move(comm.s3_config_)),
|
||||
s3_client_(std::move(comm.s3_client_)) {
|
||||
comm.active_ = false;
|
||||
|
||||
polling::instance().set_callback(
|
||||
{"s3_directory_cache", polling::frequency::high,
|
||||
[this]() { this->clear_expired_directories(); }});
|
||||
}
|
||||
|
||||
s3_comm::~s3_comm() {
|
||||
if (active_) {
|
||||
polling::instance().remove_callback("s3_directory_cache");
|
||||
}
|
||||
}
|
||||
|
||||
void s3_comm::clear_expired_directories() {
|
||||
recur_mutex_lock l(cached_directories_mutex_);
|
||||
std::vector<std::string> expired_list;
|
||||
for (const auto &kv : cached_directories_) {
|
||||
if (kv.second.expiration <= std::chrono::system_clock::now()) {
|
||||
expired_list.emplace_back(kv.first);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &expired : expired_list) {
|
||||
event_system::instance().raise<debug_log>(__FUNCTION__, expired, "expired");
|
||||
cached_directories_.erase(expired);
|
||||
}
|
||||
}
|
||||
|
||||
auto s3_comm::create_directory(const std::string &api_path) -> api_error {
|
||||
raise_begin(__FUNCTION__, api_path);
|
||||
|
||||
long response_code{};
|
||||
|
||||
auto object_name = get_object_name(api_path, empty_key) + '/';
|
||||
if (not create_directory_object_request(*s3_client_, s3_config_, object_name,
|
||||
response_code)) {
|
||||
return raise_end(__FUNCTION__, api_path, api_error::comm_error,
|
||||
response_code);
|
||||
}
|
||||
|
||||
return raise_end(__FUNCTION__, api_path,
|
||||
response_code == 200 ? api_error::success
|
||||
: api_error::comm_error,
|
||||
response_code);
|
||||
}
|
||||
|
||||
auto s3_comm::directory_exists(const std::string &api_path) const -> api_error {
|
||||
raise_begin(__FUNCTION__, api_path);
|
||||
|
||||
auto object_name = get_object_name(api_path, empty_key) + "/";
|
||||
|
||||
head_object_result result{};
|
||||
long response_code{};
|
||||
if (head_object_request(*s3_client_, s3_config_, object_name, result,
|
||||
response_code)) {
|
||||
if (response_code == 404) {
|
||||
return raise_end(__FUNCTION__, api_path, api_error::directory_not_found,
|
||||
response_code);
|
||||
}
|
||||
|
||||
return raise_end(__FUNCTION__, api_path, api_error::directory_exists,
|
||||
response_code);
|
||||
}
|
||||
|
||||
return raise_end(__FUNCTION__, api_path, api_error::comm_error,
|
||||
response_code);
|
||||
}
|
||||
|
||||
auto s3_comm::file_exists(const std::string &api_path,
|
||||
const get_key_callback &get_key) const -> api_error {
|
||||
raise_begin(__FUNCTION__, api_path);
|
||||
|
||||
if (get_cached_file_exists(api_path)) {
|
||||
return raise_end(__FUNCTION__, api_path, api_error::item_exists, 200);
|
||||
}
|
||||
|
||||
auto object_name = get_object_name(api_path, get_key);
|
||||
|
||||
head_object_result result{};
|
||||
long response_code{};
|
||||
if (head_object_request(*s3_client_, s3_config_, object_name, result,
|
||||
response_code)) {
|
||||
if (response_code == 404) {
|
||||
return raise_end(__FUNCTION__, api_path, api_error::item_not_found,
|
||||
response_code);
|
||||
}
|
||||
|
||||
return raise_end(__FUNCTION__, api_path, api_error::item_exists,
|
||||
response_code);
|
||||
}
|
||||
|
||||
return raise_end(__FUNCTION__, api_path, api_error::directory_exists,
|
||||
response_code);
|
||||
}
|
||||
|
||||
auto s3_comm::get_object_list(std::vector<directory_item> &list) const
|
||||
-> api_error {
|
||||
raise_begin(__FUNCTION__, "/");
|
||||
|
||||
long response_code{};
|
||||
auto success =
|
||||
list_objects_request(*s3_client_, s3_config_, list, response_code);
|
||||
return raise_end(__FUNCTION__, "/",
|
||||
success ? api_error::success : api_error::comm_error,
|
||||
response_code);
|
||||
}
|
||||
|
||||
auto s3_comm::get_object_name(const std::string &api_path,
|
||||
const get_key_callback &get_key) const
|
||||
-> std::string {
|
||||
auto object_name = utils::path::create_api_path(api_path).substr(1);
|
||||
|
||||
const auto key = get_key();
|
||||
if (not key.empty()) {
|
||||
auto parts = utils::string::split(object_name, '/', false);
|
||||
parts[parts.size() - 1u] = key;
|
||||
object_name = utils::string::join(parts, '/');
|
||||
}
|
||||
|
||||
return object_name;
|
||||
}
|
||||
|
||||
auto s3_comm::get_cached_directory_item_count(const std::string &api_path,
|
||||
std::size_t &count) const
|
||||
-> bool {
|
||||
recur_mutex_lock l(cached_directories_mutex_);
|
||||
if (cached_directories_.find(api_path) != cached_directories_.end()) {
|
||||
count = cached_directories_.at(api_path).items.size();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
auto s3_comm::get_cached_directory_items(const std::string &api_path,
|
||||
meta_provider_callback meta_provider,
|
||||
directory_item_list &list) const
|
||||
-> bool {
|
||||
unique_recur_mutex_lock l(cached_directories_mutex_);
|
||||
if (cached_directories_.find(api_path) != cached_directories_.end()) {
|
||||
auto &cachedEntry = cached_directories_.at(api_path);
|
||||
list = cachedEntry.items;
|
||||
cached_directories_[api_path].reset_timeout(
|
||||
std::chrono::seconds(config_.get_s3_config().cache_timeout_secs));
|
||||
l.unlock();
|
||||
|
||||
for (auto &item : list) {
|
||||
meta_provider(item);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
auto s3_comm::get_cached_file_exists(const std::string &api_path) const
|
||||
-> bool {
|
||||
unique_recur_mutex_lock l(cached_directories_mutex_);
|
||||
const auto parent_api_path = utils::path::get_parent_api_path(api_path);
|
||||
if (cached_directories_.find(parent_api_path) != cached_directories_.end()) {
|
||||
auto &entry = cached_directories_.at(parent_api_path);
|
||||
if (std::find_if(entry.items.begin(), entry.items.end(),
|
||||
[&api_path](const auto &item) -> bool {
|
||||
return not item.directory && (api_path == item.api_path);
|
||||
}) != entry.items.end()) {
|
||||
cached_directories_[api_path].reset_timeout(
|
||||
std::chrono::seconds(config_.get_s3_config().cache_timeout_secs));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
auto s3_comm::get_directory_item_count(
|
||||
const std::string &api_path, meta_provider_callback meta_provider) const
|
||||
-> std::size_t {
|
||||
raise_begin(__FUNCTION__, api_path);
|
||||
|
||||
std::size_t ret = 0u;
|
||||
if (not get_cached_directory_item_count(api_path, ret)) {
|
||||
directory_item_list list;
|
||||
const auto res = grab_directory_items(api_path, meta_provider, list);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res,
|
||||
"failed to grab directory items");
|
||||
}
|
||||
return list.size();
|
||||
}
|
||||
|
||||
if (config_.get_event_level() >= event_level::debug) {
|
||||
event_system::instance().raise<debug_log>(__FUNCTION__, api_path,
|
||||
"end|" + std::to_string(ret));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto s3_comm::get_directory_items(const std::string &api_path,
|
||||
meta_provider_callback meta_provider,
|
||||
directory_item_list &list) const
|
||||
-> api_error {
|
||||
raise_begin(__FUNCTION__, api_path);
|
||||
|
||||
auto ret = api_error::success;
|
||||
if (not get_cached_directory_items(api_path, meta_provider, list)) {
|
||||
ret = grab_directory_items(api_path, meta_provider, list);
|
||||
}
|
||||
|
||||
if (config_.get_event_level() >= event_level::debug) {
|
||||
event_system::instance().raise<debug_log>(
|
||||
__FUNCTION__, api_path, "end|" + api_error_to_string(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto s3_comm::get_directory_list(api_file_list &list) const -> api_error {
|
||||
raise_begin(__FUNCTION__, "/");
|
||||
|
||||
long response_code{};
|
||||
auto success =
|
||||
list_directories_request(*s3_client_, s3_config_, list, response_code);
|
||||
return raise_end(__FUNCTION__, "/",
|
||||
success ? api_error::success : api_error::comm_error,
|
||||
response_code);
|
||||
}
|
||||
|
||||
auto s3_comm::get_file(const std::string &api_path,
|
||||
const get_key_callback &get_key,
|
||||
const get_name_callback &get_name,
|
||||
const get_token_callback &get_token,
|
||||
api_file &file) const -> api_error {
|
||||
raise_begin(__FUNCTION__, api_path);
|
||||
|
||||
auto ret = api_error::success;
|
||||
|
||||
auto object_name = get_object_name(api_path, get_key);
|
||||
|
||||
head_object_result result{};
|
||||
long response_code{};
|
||||
if (head_object_request(*s3_client_, s3_config_, object_name, result,
|
||||
response_code)) {
|
||||
const auto key = get_key();
|
||||
object_name = get_name(key, object_name);
|
||||
file.accessed_date = utils::get_file_time_now();
|
||||
file.api_path = utils::path::create_api_path(object_name);
|
||||
file.api_parent = utils::path::get_parent_api_path(file.api_path);
|
||||
file.changed_date = utils::aws::format_time(result.last_modified);
|
||||
file.creation_date = utils::aws::format_time(result.last_modified);
|
||||
file.encryption_token = get_token();
|
||||
file.file_size =
|
||||
file.encryption_token.empty()
|
||||
? result.content_length
|
||||
: utils::encryption::encrypting_reader::calculate_decrypted_size(
|
||||
result.content_length);
|
||||
file.modified_date = utils::aws::format_time(result.last_modified);
|
||||
} else {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, response_code,
|
||||
"head object request failed");
|
||||
ret = api_error::comm_error;
|
||||
}
|
||||
|
||||
if (config_.get_event_level() >= event_level::debug) {
|
||||
event_system::instance().raise<debug_log>(
|
||||
__FUNCTION__, api_path, "end|" + api_error_to_string(ret));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto s3_comm::get_file_list(
|
||||
const get_api_file_token_callback &get_api_file_token,
|
||||
const get_name_callback &get_name, api_file_list &list) const -> api_error {
|
||||
raise_begin(__FUNCTION__, "/");
|
||||
|
||||
long response_code{};
|
||||
auto success = list_files_request(*s3_client_, s3_config_, get_api_file_token,
|
||||
get_name, list, response_code);
|
||||
return raise_end(__FUNCTION__, "/",
|
||||
success ? api_error::success : api_error::comm_error,
|
||||
response_code);
|
||||
}
|
||||
|
||||
auto s3_comm::grab_directory_items(const std::string &api_path,
|
||||
meta_provider_callback meta_provider,
|
||||
directory_item_list &list) const
|
||||
-> api_error {
|
||||
auto object_name = get_object_name(api_path, empty_key);
|
||||
long response_code{};
|
||||
if (list_objects_in_directory_request(*s3_client_, s3_config_, object_name,
|
||||
meta_provider, list, response_code)) {
|
||||
if (response_code == 404) {
|
||||
return api_error::directory_not_found;
|
||||
}
|
||||
|
||||
if (response_code != 200) {
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
||||
set_cached_directory_items(api_path, list);
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
||||
void s3_comm::raise_begin(const std::string &function_name,
|
||||
const std::string &api_path) const {
|
||||
if (config_.get_event_level() >= event_level::debug) {
|
||||
event_system::instance().raise<debug_log>(function_name, api_path,
|
||||
"begin|");
|
||||
}
|
||||
}
|
||||
|
||||
auto s3_comm::raise_end(const std::string &function_name,
|
||||
const std::string &api_path, const api_error &error,
|
||||
long code) const -> api_error {
|
||||
if (config_.get_event_level() >= event_level::debug) {
|
||||
event_system::instance().raise<debug_log>(
|
||||
function_name, api_path,
|
||||
"end|" + api_error_to_string(error) + '|' + std::to_string(code));
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
auto s3_comm::read_file_bytes(const std::string &api_path, std::size_t size,
|
||||
std::uint64_t offset, data_buffer &data,
|
||||
const get_key_callback &get_key,
|
||||
const get_size_callback &get_size,
|
||||
const get_token_callback &get_token,
|
||||
stop_type &stop_requested) const -> api_error {
|
||||
data.clear();
|
||||
|
||||
auto object_name = get_object_name(api_path, get_key);
|
||||
|
||||
const auto encryption_token = get_token();
|
||||
const auto data_size = get_size();
|
||||
if (encryption_token.empty()) {
|
||||
long response_code{};
|
||||
if (not read_object_request(*s3_client_, s3_config_, object_name, size,
|
||||
offset, data, response_code, stop_requested)) {
|
||||
auto res =
|
||||
stop_requested ? api_error::download_stopped : api_error::comm_error;
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res,
|
||||
"failed to read file bytes");
|
||||
return res;
|
||||
}
|
||||
|
||||
if (response_code < 200 || response_code >= 300) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, response_code,
|
||||
"failed to read file bytes");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
const auto key = utils::encryption::generate_key(encryption_token);
|
||||
return utils::encryption::read_encrypted_range(
|
||||
{offset, offset + size - 1}, key,
|
||||
[&](data_buffer &ct, std::uint64_t start_offset,
|
||||
std::uint64_t end_offset) -> api_error {
|
||||
return read_file_bytes(
|
||||
api_path, (end_offset - start_offset + 1u), start_offset, ct,
|
||||
get_key, get_size, []() -> std::string { return ""; },
|
||||
stop_requested);
|
||||
},
|
||||
data_size, data);
|
||||
}
|
||||
|
||||
void s3_comm::remove_cached_directory(const std::string &api_path) {
|
||||
recur_mutex_lock l(cached_directories_mutex_);
|
||||
cached_directories_.erase(api_path);
|
||||
}
|
||||
|
||||
auto s3_comm::remove_directory(const std::string &api_path) -> api_error {
|
||||
raise_begin(__FUNCTION__, api_path);
|
||||
|
||||
auto object_name = get_object_name(api_path, empty_key) + "/";
|
||||
|
||||
long response_code{};
|
||||
if (delete_object_request(*s3_client_, s3_config_, object_name,
|
||||
response_code)) {
|
||||
if (response_code == 404) {
|
||||
return raise_end(__FUNCTION__, api_path, api_error::directory_not_found,
|
||||
response_code);
|
||||
}
|
||||
|
||||
if (response_code != 204) {
|
||||
return raise_end(__FUNCTION__, api_path, api_error::comm_error,
|
||||
response_code);
|
||||
}
|
||||
|
||||
remove_cached_directory(utils::path::get_parent_api_path(api_path));
|
||||
remove_cached_directory(api_path);
|
||||
|
||||
return raise_end(__FUNCTION__, api_path, api_error::success, response_code);
|
||||
}
|
||||
|
||||
return raise_end(__FUNCTION__, api_path, api_error::comm_error,
|
||||
response_code);
|
||||
}
|
||||
|
||||
auto s3_comm::remove_file(const std::string &api_path,
|
||||
const get_key_callback &get_key) -> api_error {
|
||||
raise_begin(__FUNCTION__, api_path);
|
||||
|
||||
auto object_name = get_object_name(api_path, get_key);
|
||||
|
||||
long response_code{};
|
||||
if (delete_object_request(*s3_client_, s3_config_, object_name,
|
||||
response_code)) {
|
||||
if (response_code == 404) {
|
||||
return raise_end(__FUNCTION__, api_path, api_error::item_not_found,
|
||||
response_code);
|
||||
}
|
||||
|
||||
if (response_code != 204) {
|
||||
return raise_end(__FUNCTION__, api_path, api_error::comm_error,
|
||||
response_code);
|
||||
}
|
||||
|
||||
remove_cached_directory(utils::path::get_parent_api_path(api_path));
|
||||
return raise_end(__FUNCTION__, api_path, api_error::success, response_code);
|
||||
}
|
||||
|
||||
return raise_end(__FUNCTION__, api_path, api_error::comm_error,
|
||||
response_code);
|
||||
}
|
||||
|
||||
auto s3_comm::rename_file(const std::string & /*api_path*/,
|
||||
const std::string & /*new_api_path*/) -> api_error {
|
||||
return api_error::not_implemented;
|
||||
/* if (config_.get_event_level() >= event_level::debug) { */
|
||||
/* event_system::instance().raise<debug_log>(__FUNCTION__, api_path,
|
||||
* "begin"); */
|
||||
/* } */
|
||||
/* auto ret = api_error::success; */
|
||||
/* */
|
||||
/* std::string bucket_name, object_name; */
|
||||
/* get_object_name(api_path, bucket_name, object_name); */
|
||||
/* */
|
||||
/* std::string new_object_name; */
|
||||
/* get_object_name(new_api_path, bucket_name, new_object_name); */
|
||||
/* */
|
||||
/* Aws::S3::Model::CopyObjectRequest request{}; */
|
||||
/* request.SetBucket(bucket_name); */
|
||||
/* request.SetCopySource(bucket_name + '/' + object_name); */
|
||||
/* request.SetKey(new_object_name); */
|
||||
/* */
|
||||
/* const auto outcome = s3_client_->CopyObject(request); */
|
||||
/* if (outcome.IsSuccess()) { */
|
||||
/* ret = remove_file(api_path); */
|
||||
/* } else { */
|
||||
/* const auto &error = outcome.GetError(); */
|
||||
/* event_system::instance().raise<repertory_exception>(__FUNCTION__,
|
||||
* error.GetExceptionName()
|
||||
* +
|
||||
* "|" + */
|
||||
/* error.GetMessage());
|
||||
*/
|
||||
/* ret = api_error::comm_error; */
|
||||
/* } */
|
||||
/* */
|
||||
/* if (config_.get_event_level() >= event_level::debug) { */
|
||||
/* event_system::instance().raise<debug_log>(__FUNCTION__, api_path, */
|
||||
/* "end|" +
|
||||
* std::to_string(std::uint8_t(ret))); */
|
||||
/* } */
|
||||
/* return ret; */
|
||||
}
|
||||
|
||||
void s3_comm::set_cached_directory_items(const std::string &api_path,
|
||||
directory_item_list list) const {
|
||||
recur_mutex_lock l(cached_directories_mutex_);
|
||||
cached_directories_[api_path].items = std::move(list);
|
||||
cached_directories_[api_path].reset_timeout(
|
||||
std::chrono::seconds(config_.get_s3_config().cache_timeout_secs));
|
||||
}
|
||||
|
||||
auto s3_comm::upload_file(const std::string &api_path,
|
||||
const std::string &source_path,
|
||||
const std::string &encryption_token,
|
||||
const get_key_callback &get_key,
|
||||
const set_key_callback &set_key,
|
||||
stop_type &stop_requested) -> api_error {
|
||||
raise_begin(__FUNCTION__, api_path);
|
||||
|
||||
auto object_name = get_object_name(api_path, get_key);
|
||||
long response_code{};
|
||||
if (not put_object_request(*s3_client_, s3_config_, object_name, source_path,
|
||||
encryption_token, get_key, set_key, response_code,
|
||||
stop_requested)) {
|
||||
return raise_end(__FUNCTION__, api_path,
|
||||
stop_requested ? api_error::upload_stopped
|
||||
: api_error::upload_failed,
|
||||
response_code);
|
||||
}
|
||||
|
||||
if (response_code != 200) {
|
||||
return raise_end(__FUNCTION__, api_path, api_error::comm_error,
|
||||
response_code);
|
||||
}
|
||||
|
||||
remove_cached_directory(utils::path::get_parent_api_path(api_path));
|
||||
return raise_end(__FUNCTION__, api_path, api_error::success, response_code);
|
||||
}
|
||||
} // namespace repertory
|
||||
|
||||
#endif // REPERTORY_ENABLE_S3
|
@ -37,6 +37,7 @@ get_object_list(i_http_comm &client, const s3_config &config,
|
||||
std::optional<std::string> delimiter = std::nullopt,
|
||||
std::optional<std::string> prefix = std::nullopt) -> bool {
|
||||
curl::requests::http_get get{};
|
||||
get.allow_timeout = true;
|
||||
get.aws_service = "aws:amz:" + config.region + ":s3";
|
||||
get.path = '/';
|
||||
get.query["list-type"] = "2";
|
||||
@ -62,9 +63,8 @@ auto create_directory_object_request_impl(i_http_comm &client,
|
||||
long &response_code) -> bool {
|
||||
try {
|
||||
curl::requests::http_put_file put_file{};
|
||||
put_file.allow_timeout = true;
|
||||
put_file.aws_service = "aws:amz:" + config.region + ":s3";
|
||||
put_file.file_name =
|
||||
*(utils::string::split(object_name, '/', false).end() - 1U);
|
||||
put_file.path = '/' + object_name;
|
||||
|
||||
stop_type stop_requested{false};
|
||||
@ -86,11 +86,12 @@ auto delete_object_request_impl(i_http_comm &client, const s3_config &config,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response_code == 404) {
|
||||
if (response_code == http_error_codes::not_found) {
|
||||
return true;
|
||||
}
|
||||
|
||||
curl::requests::http_delete del{};
|
||||
del.allow_timeout = true;
|
||||
del.aws_service = "aws:amz:" + config.region + ":s3";
|
||||
del.path = '/' + object_name;
|
||||
|
||||
@ -109,6 +110,7 @@ auto head_object_request_impl(i_http_comm &client, const s3_config &config,
|
||||
-> bool {
|
||||
try {
|
||||
curl::requests::http_head head{};
|
||||
head.allow_timeout = true;
|
||||
head.aws_service = "aws:amz:" + config.region + ":s3";
|
||||
head.path = '/' + object_name;
|
||||
head.response_headers = http_headers{};
|
||||
@ -118,7 +120,7 @@ auto head_object_request_impl(i_http_comm &client, const s3_config &config,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response_code == 200) {
|
||||
if (response_code == http_error_codes::ok) {
|
||||
result.from_headers(head.response_headers.value());
|
||||
}
|
||||
|
||||
@ -139,7 +141,7 @@ auto list_directories_request_impl(i_http_comm &client, const s3_config &config,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response_code != 200) {
|
||||
if (response_code != http_error_codes::ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -151,7 +153,7 @@ auto list_directories_request_impl(i_http_comm &client, const s3_config &config,
|
||||
|
||||
auto node_list = doc.select_nodes("/ListBucketResult/Contents");
|
||||
for (const auto &node : node_list) {
|
||||
auto object_name =
|
||||
const auto *object_name =
|
||||
node.node().select_node("Key").node().text().as_string();
|
||||
if (utils::string::ends_with(object_name, "/")) {
|
||||
api_file directory{};
|
||||
@ -186,7 +188,7 @@ auto list_files_request_impl(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response_code != 200) {
|
||||
if (response_code != http_error_codes::ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -203,17 +205,17 @@ auto list_files_request_impl(
|
||||
if (not utils::string::ends_with(object_name, "/")) {
|
||||
api_file file{};
|
||||
object_name = get_name(
|
||||
*(utils::string::split(object_name, '/', false).end() - 1u),
|
||||
*(utils::string::split(object_name, '/', false).end() - 1U),
|
||||
object_name);
|
||||
file.api_path = utils::path::create_api_path(object_name);
|
||||
file.api_parent = utils::path::get_parent_api_path(file.api_path);
|
||||
file.accessed_date = utils::get_file_time_now();
|
||||
file.encryption_token = get_api_file_token(file.api_path);
|
||||
// file.encryption_token = get_api_file_token(file.api_path);
|
||||
auto size = node.node().select_node("Size").node().text().as_ullong();
|
||||
file.file_size = file.encryption_token.empty()
|
||||
? size
|
||||
: utils::encryption::encrypting_reader::
|
||||
calculate_decrypted_size(size);
|
||||
// file.file_size = file.encryption_token.empty()
|
||||
// ? size
|
||||
// : utils::encryption::encrypting_reader::
|
||||
// calculate_decrypted_size(size);
|
||||
file.changed_date = utils::convert_api_date(
|
||||
node.node().select_node("LastModified").node().text().as_string());
|
||||
file.creation_date = file.changed_date;
|
||||
@ -242,7 +244,7 @@ auto list_objects_in_directory_request_impl(
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response_code != 200) {
|
||||
if (response_code != http_error_codes::ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -255,14 +257,15 @@ auto list_objects_in_directory_request_impl(
|
||||
const auto add_directory_item =
|
||||
[&](bool directory, const std::string &name,
|
||||
std::function<std::uint64_t(const directory_item &)> get_size) {
|
||||
directory_item di{};
|
||||
di.api_path =
|
||||
directory_item dir_item{};
|
||||
dir_item.api_path =
|
||||
utils::path::create_api_path(utils::path::combine("/", {name}));
|
||||
di.api_parent = utils::path::get_parent_api_path(di.api_path);
|
||||
di.directory = directory;
|
||||
di.size = get_size(di);
|
||||
meta_provider(di);
|
||||
result.emplace_back(std::move(di));
|
||||
dir_item.api_parent =
|
||||
utils::path::get_parent_api_path(dir_item.api_path);
|
||||
dir_item.directory = directory;
|
||||
dir_item.size = get_size(dir_item);
|
||||
meta_provider(dir_item);
|
||||
result.emplace_back(std::move(dir_item));
|
||||
};
|
||||
|
||||
auto node_list =
|
||||
@ -275,7 +278,7 @@ auto list_objects_in_directory_request_impl(
|
||||
|
||||
node_list = doc.select_nodes("/ListBucketResult/Contents");
|
||||
for (const auto &node : node_list) {
|
||||
auto child_object_name =
|
||||
const auto *child_object_name =
|
||||
node.node().select_node("Key").node().text().as_string();
|
||||
if (child_object_name != prefix) {
|
||||
auto size = node.node().select_node("Size").node().text().as_ullong();
|
||||
@ -302,7 +305,7 @@ auto list_objects_request_impl(i_http_comm &client, const s3_config &config,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response_code != 200) {
|
||||
if (response_code != http_error_codes::ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -314,16 +317,16 @@ auto list_objects_request_impl(i_http_comm &client, const s3_config &config,
|
||||
|
||||
auto node_list = doc.select_nodes("/ListBucketResult/Contents");
|
||||
for (const auto &node : node_list) {
|
||||
auto object_name =
|
||||
const auto *object_name =
|
||||
node.node().select_node("Key").node().text().as_string();
|
||||
auto size = node.node().select_node("Size").node().text().as_ullong();
|
||||
directory_item di{};
|
||||
di.api_path = utils::path::create_api_path(object_name);
|
||||
di.api_parent = utils::path::get_parent_api_path(di.api_path);
|
||||
di.directory = utils::string::ends_with(object_name, "/");
|
||||
di.size = di.directory ? 0U : size;
|
||||
di.resolved = false;
|
||||
result.emplace_back(std::move(di));
|
||||
directory_item dir_item{};
|
||||
dir_item.api_path = utils::path::create_api_path(object_name);
|
||||
dir_item.api_parent = utils::path::get_parent_api_path(dir_item.api_path);
|
||||
dir_item.directory = utils::string::ends_with(object_name, "/");
|
||||
dir_item.size = dir_item.directory ? 0U : size;
|
||||
dir_item.resolved = false;
|
||||
result.emplace_back(std::move(dir_item));
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -344,9 +347,6 @@ auto put_object_request_impl(i_http_comm &client, const s3_config &config,
|
||||
try {
|
||||
curl::requests::http_put_file put_file{};
|
||||
put_file.aws_service = "aws:amz:" + config.region + ":s3";
|
||||
put_file.encryption_token = encryption_token;
|
||||
put_file.file_name =
|
||||
*(utils::string::split(object_name, '/', false).end() - 1U);
|
||||
put_file.path = '/' + object_name;
|
||||
put_file.source_path = source_path;
|
||||
|
||||
@ -354,8 +354,8 @@ auto put_object_request_impl(i_http_comm &client, const s3_config &config,
|
||||
static stop_type no_stop{false};
|
||||
|
||||
put_file.reader = std::make_shared<utils::encryption::encrypting_reader>(
|
||||
put_file.file_name, source_path, no_stop, encryption_token,
|
||||
std::nullopt, -1);
|
||||
*(utils::string::split(object_name, '/', false).end() - 1U),
|
||||
source_path, no_stop, encryption_token, std::nullopt, -1);
|
||||
auto key = get_key();
|
||||
if (key.empty()) {
|
||||
key = put_file.reader->get_encrypted_file_name();
|
||||
|
@ -20,6 +20,7 @@
|
||||
SOFTWARE.
|
||||
*/
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
auto get_repertory_git_revision() -> const std::string & {
|
||||
|
@ -1,370 +0,0 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#include "db/directory_db.hpp"
|
||||
|
||||
#include "utils/path_utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
void directory_db::directory_tree::add_path(
|
||||
const std::string &api_path, const std::vector<std::string> &files,
|
||||
rocksdb::DB &db) {
|
||||
const auto create_not_found = [&](const auto &create_path) {
|
||||
std::string value;
|
||||
if (not db.Get(rocksdb::ReadOptions(), create_path, &value).ok()) {
|
||||
json directoryData = {
|
||||
{"path", api_path},
|
||||
{"files", files},
|
||||
};
|
||||
db.Put(rocksdb::WriteOptions(), create_path, directoryData.dump());
|
||||
}
|
||||
};
|
||||
|
||||
const auto parts = utils::string::split(api_path, '/', false);
|
||||
std::string previous_directory;
|
||||
for (const auto &directory_part : parts) {
|
||||
if (directory_part.empty()) {
|
||||
sub_directory_lookup_["/"];
|
||||
previous_directory = "/";
|
||||
create_not_found("/");
|
||||
} else {
|
||||
auto &sub_directories = sub_directory_lookup_[previous_directory];
|
||||
if (std::find(sub_directories.begin(), sub_directories.end(),
|
||||
directory_part) == sub_directories.end()) {
|
||||
sub_directories.emplace_back(directory_part);
|
||||
}
|
||||
previous_directory = utils::path::create_api_path(
|
||||
utils::path::combine(previous_directory, {directory_part}));
|
||||
sub_directory_lookup_[previous_directory];
|
||||
create_not_found(previous_directory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto directory_db::directory_tree::get_count(const std::string &api_path) const
|
||||
-> std::size_t {
|
||||
return (sub_directory_lookup_.find(api_path) == sub_directory_lookup_.end())
|
||||
? 0
|
||||
: sub_directory_lookup_.at(api_path).size();
|
||||
}
|
||||
|
||||
auto directory_db::directory_tree::get_directories() const
|
||||
-> std::vector<std::string> {
|
||||
std::vector<std::string> ret;
|
||||
std::transform(sub_directory_lookup_.begin(), sub_directory_lookup_.end(),
|
||||
std::back_inserter(ret),
|
||||
[](const auto &kv) { return kv.first; });
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto directory_db::directory_tree::get_sub_directories(
|
||||
const std::string &api_path) const -> std::vector<std::string> {
|
||||
std::vector<std::string> ret;
|
||||
if (sub_directory_lookup_.find(api_path) != sub_directory_lookup_.end()) {
|
||||
const auto &lookup = sub_directory_lookup_.at(api_path);
|
||||
std::transform(lookup.begin(), lookup.end(), std::back_inserter(ret),
|
||||
[&api_path](const auto &directory) {
|
||||
return utils::path::create_api_path(
|
||||
utils::path::combine(api_path, {directory}));
|
||||
});
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto directory_db::directory_tree::is_directory(
|
||||
const std::string &api_path) const -> bool {
|
||||
return sub_directory_lookup_.find(api_path) != sub_directory_lookup_.end();
|
||||
}
|
||||
|
||||
void directory_db::directory_tree::remove_directory(const std::string &api_path,
|
||||
rocksdb::DB &db,
|
||||
bool allow_remove_root) {
|
||||
if ((allow_remove_root || (api_path != "/")) && is_directory(api_path)) {
|
||||
sub_directory_lookup_.erase(api_path);
|
||||
db.Delete(rocksdb::WriteOptions(), api_path);
|
||||
|
||||
const auto parent_api_path = utils::path::get_parent_api_path(api_path);
|
||||
const auto parts = utils::string::split(api_path, '/', false);
|
||||
utils::remove_element_from(sub_directory_lookup_[parent_api_path],
|
||||
parts[parts.size() - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
directory_db::directory_db(const app_config &config) {
|
||||
utils::db::create_rocksdb(config, DIRDB_NAME, db_);
|
||||
auto iterator = std::unique_ptr<rocksdb::Iterator>(
|
||||
db_->NewIterator(rocksdb::ReadOptions()));
|
||||
for (iterator->SeekToFirst(); iterator->Valid(); iterator->Next()) {
|
||||
auto directory_data = json::parse(iterator->value().ToString());
|
||||
tree_.add_path(directory_data["path"].get<std::string>(),
|
||||
directory_data["files"].get<std::vector<std::string>>(),
|
||||
*db_);
|
||||
}
|
||||
}
|
||||
|
||||
directory_db::~directory_db() { db_.reset(); }
|
||||
|
||||
auto directory_db::create_directory(const std::string &api_path,
|
||||
bool create_always) -> api_error {
|
||||
recur_mutex_lock directory_lock(directory_mutex_);
|
||||
auto ret = api_error::directory_exists;
|
||||
if (not is_directory(api_path)) {
|
||||
ret = api_error::directory_not_found;
|
||||
if (create_always || (api_path == "/") ||
|
||||
is_directory(utils::path::get_parent_api_path(api_path))) {
|
||||
ret = api_error::item_exists;
|
||||
if (not is_file(api_path)) {
|
||||
tree_.add_path(api_path, {}, *db_);
|
||||
ret = api_error::success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto directory_db::create_file(const std::string &api_path) -> api_error {
|
||||
recur_mutex_lock directory_lock(directory_mutex_);
|
||||
if (is_directory(api_path)) {
|
||||
return api_error::directory_exists;
|
||||
}
|
||||
|
||||
const auto parent_api_path = utils::path::get_parent_api_path(api_path);
|
||||
auto directory_data = get_directory_data(parent_api_path);
|
||||
if (directory_data.empty()) {
|
||||
return api_error::directory_not_found;
|
||||
}
|
||||
|
||||
const auto file_name = utils::path::strip_to_file_name(api_path);
|
||||
if (utils::collection_includes(directory_data["files"], file_name)) {
|
||||
return api_error::item_exists;
|
||||
}
|
||||
|
||||
directory_data["files"].emplace_back(file_name);
|
||||
db_->Put(rocksdb::WriteOptions(), parent_api_path, directory_data.dump());
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto directory_db::get_directory_data(const std::string &api_path) const
|
||||
-> json {
|
||||
std::string data;
|
||||
db_->Get(rocksdb::ReadOptions(), api_path, &data);
|
||||
if (data.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return json::parse(data);
|
||||
}
|
||||
|
||||
auto directory_db::get_directory_item_count(const std::string &api_path) const
|
||||
-> std::uint64_t {
|
||||
auto directory_data = get_directory_data(api_path);
|
||||
const auto sub_directory_count = get_sub_directory_count(api_path);
|
||||
const auto file_count =
|
||||
(directory_data.empty() ? 0 : directory_data["files"].size());
|
||||
return sub_directory_count + file_count;
|
||||
}
|
||||
|
||||
auto directory_db::get_file(const std::string &api_path, api_file &file,
|
||||
api_file_provider_callback api_file_provider) const
|
||||
-> api_error {
|
||||
const auto parent_api_path = utils::path::get_parent_api_path(api_path);
|
||||
auto directory_data = get_directory_data(parent_api_path);
|
||||
if (not directory_data.empty()) {
|
||||
const auto file_name = utils::path::strip_to_file_name(api_path);
|
||||
if (utils::collection_includes(directory_data["files"], file_name)) {
|
||||
file.api_path = utils::path::create_api_path(
|
||||
utils::path::combine(parent_api_path, {file_name})),
|
||||
api_file_provider(file);
|
||||
return api_error::success;
|
||||
}
|
||||
}
|
||||
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
auto directory_db::get_file_list(
|
||||
api_file_list &list, api_file_provider_callback api_file_provider) const
|
||||
-> api_error {
|
||||
auto iterator = std::unique_ptr<rocksdb::Iterator>(
|
||||
db_->NewIterator(rocksdb::ReadOptions()));
|
||||
for (iterator->SeekToFirst(); iterator->Valid(); iterator->Next()) {
|
||||
auto directory_data = json::parse(iterator->value().ToString());
|
||||
for (const auto &directory_file : directory_data["files"]) {
|
||||
api_file file{
|
||||
utils::path::create_api_path(utils::path::combine(
|
||||
iterator->key().ToString(), {directory_file.get<std::string>()})),
|
||||
};
|
||||
api_file_provider(file);
|
||||
list.emplace_back(file);
|
||||
}
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto directory_db::get_sub_directory_count(const std::string &api_path) const
|
||||
-> std::size_t {
|
||||
recur_mutex_lock directoryLock(directory_mutex_);
|
||||
return tree_.get_count(api_path);
|
||||
}
|
||||
|
||||
auto directory_db::get_total_item_count() const -> std::uint64_t {
|
||||
unique_recur_mutex_lock directory_lock(directory_mutex_);
|
||||
const auto directories = tree_.get_directories();
|
||||
directory_lock.unlock();
|
||||
|
||||
return std::accumulate(
|
||||
directories.begin(), directories.end(), std::uint64_t(directories.size()),
|
||||
[this](std::uint64_t c, const std::string &directory) {
|
||||
const auto dirData = this->get_directory_data(directory);
|
||||
return c + (dirData.empty() ? 0 : dirData["files"].size());
|
||||
});
|
||||
}
|
||||
|
||||
auto directory_db::is_directory(const std::string &api_path) const -> bool {
|
||||
recur_mutex_lock directory_lock(directory_mutex_);
|
||||
return tree_.is_directory(api_path);
|
||||
}
|
||||
|
||||
auto directory_db::is_file(const std::string &api_path) const -> bool {
|
||||
auto directory_data =
|
||||
get_directory_data(utils::path::get_parent_api_path(api_path));
|
||||
if (directory_data.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto file_name = utils::path::strip_to_file_name(api_path);
|
||||
return utils::collection_includes(directory_data["files"], file_name);
|
||||
}
|
||||
|
||||
void directory_db::populate_directory_files(
|
||||
const std::string &api_path, meta_provider_callback meta_provider,
|
||||
directory_item_list &list) const {
|
||||
auto directory_data = get_directory_data(api_path);
|
||||
if (not directory_data.empty()) {
|
||||
for (const auto &directory_file : directory_data["files"]) {
|
||||
directory_item di{};
|
||||
di.api_path = utils::path::create_api_path(
|
||||
utils::path::combine(api_path, {directory_file.get<std::string>()}));
|
||||
di.directory = false;
|
||||
meta_provider(di);
|
||||
di.size = utils::string::to_uint64(di.meta[META_SIZE]);
|
||||
list.emplace_back(std::move(di));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void directory_db::populate_sub_directories(
|
||||
const std::string &api_path, meta_provider_callback meta_provider,
|
||||
directory_item_list &list) const {
|
||||
unique_recur_mutex_lock directory_lock(directory_mutex_);
|
||||
const auto directories = tree_.get_sub_directories(api_path);
|
||||
directory_lock.unlock();
|
||||
|
||||
std::size_t offset{};
|
||||
for (const auto &directory : directories) {
|
||||
if (std::find_if(list.begin(), list.end(),
|
||||
[&directory](const auto &di) -> bool {
|
||||
return directory == di.api_path;
|
||||
}) == list.end()) {
|
||||
directory_item di{};
|
||||
di.api_path = directory;
|
||||
di.api_parent = utils::path::get_parent_api_path(directory);
|
||||
di.directory = true;
|
||||
di.size = get_sub_directory_count(directory);
|
||||
meta_provider(di);
|
||||
|
||||
list.insert(list.begin() + static_cast<std::int64_t>(offset++),
|
||||
std::move(di));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto directory_db::remove_directory(const std::string &api_path,
|
||||
bool allow_remove_root) -> api_error {
|
||||
recur_mutex_lock directory_lock(directory_mutex_);
|
||||
if ((api_path == "/") && not allow_remove_root) {
|
||||
return api_error::access_denied;
|
||||
}
|
||||
|
||||
if (is_file(api_path) || not is_directory(api_path)) {
|
||||
return api_error::directory_not_found;
|
||||
}
|
||||
|
||||
if (tree_.get_count(api_path) == 0) {
|
||||
auto directory_data = get_directory_data(api_path);
|
||||
if (directory_data.empty() || directory_data["files"].empty()) {
|
||||
tree_.remove_directory(api_path, *db_, allow_remove_root);
|
||||
return api_error::success;
|
||||
}
|
||||
}
|
||||
|
||||
return api_error::directory_not_empty;
|
||||
}
|
||||
|
||||
auto directory_db::remove_file(const std::string &api_path) -> bool {
|
||||
recur_mutex_lock directory_lock(directory_mutex_);
|
||||
|
||||
if (is_directory(api_path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto parent_api_path = utils::path::get_parent_api_path(api_path);
|
||||
auto directory_data = get_directory_data(parent_api_path);
|
||||
if (directory_data.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto file_name = utils::path::strip_to_file_name(api_path);
|
||||
if (utils::collection_excludes(directory_data["files"], file_name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
utils::remove_element_from(directory_data["files"], file_name);
|
||||
db_->Put(rocksdb::WriteOptions(), parent_api_path, directory_data.dump());
|
||||
return true;
|
||||
}
|
||||
|
||||
auto directory_db::rename_file(const std::string &from_api_path,
|
||||
const std::string &to_api_path) -> api_error {
|
||||
recur_mutex_lock directory_lock(directory_mutex_);
|
||||
|
||||
if (is_directory(from_api_path) || is_directory(to_api_path)) {
|
||||
return api_error::directory_exists;
|
||||
}
|
||||
|
||||
if (not is_directory(utils::path::get_parent_api_path(to_api_path))) {
|
||||
return api_error::directory_not_found;
|
||||
}
|
||||
|
||||
if (is_file(to_api_path)) {
|
||||
return api_error::item_exists;
|
||||
}
|
||||
|
||||
if (not remove_file(from_api_path)) {
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
return create_file(to_api_path);
|
||||
}
|
||||
} // namespace repertory
|
@ -1,347 +0,0 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#include "db/meta_db.hpp"
|
||||
|
||||
#include "types/repertory.hpp"
|
||||
#include "types/startup_exception.hpp"
|
||||
#include "utils/error_utils.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
meta_db::meta_db(const app_config &config) {
|
||||
const auto create_resources = [this, &config](const std::string &name) {
|
||||
auto families = std::vector<rocksdb::ColumnFamilyDescriptor>();
|
||||
families.emplace_back(rocksdb::kDefaultColumnFamilyName,
|
||||
rocksdb::ColumnFamilyOptions());
|
||||
families.emplace_back("keys", rocksdb::ColumnFamilyOptions());
|
||||
families.emplace_back("source", rocksdb::ColumnFamilyOptions());
|
||||
|
||||
auto handles = std::vector<rocksdb::ColumnFamilyHandle *>();
|
||||
utils::db::create_rocksdb(config, name, families, handles, db_);
|
||||
|
||||
std::size_t idx{};
|
||||
default_family_ = handles[idx++];
|
||||
keys_family_ = handles[idx++];
|
||||
source_family_ = handles[idx++];
|
||||
};
|
||||
|
||||
create_resources(METADB_NAME);
|
||||
}
|
||||
|
||||
meta_db::~meta_db() { db_.reset(); }
|
||||
|
||||
auto meta_db::create_iterator(bool source_family) const
|
||||
-> std::shared_ptr<rocksdb::Iterator> {
|
||||
return std::shared_ptr<rocksdb::Iterator>(
|
||||
db_->NewIterator(rocksdb::ReadOptions(),
|
||||
source_family ? source_family_ : default_family_));
|
||||
}
|
||||
|
||||
auto meta_db::get_api_path_from_key(const std::string &key,
|
||||
std::string &api_path) const -> api_error {
|
||||
if (key.empty()) {
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
return perform_action(__FUNCTION__, [&]() -> rocksdb::Status {
|
||||
return db_->Get(rocksdb::ReadOptions(), keys_family_, key, &api_path);
|
||||
});
|
||||
}
|
||||
|
||||
auto meta_db::get_api_path_from_source(const std::string &source_path,
|
||||
std::string &api_path) const
|
||||
-> api_error {
|
||||
if (source_path.empty()) {
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
return perform_action(__FUNCTION__, [&]() -> rocksdb::Status {
|
||||
return db_->Get(rocksdb::ReadOptions(), source_family_, source_path,
|
||||
&api_path);
|
||||
});
|
||||
}
|
||||
|
||||
auto meta_db::get_item_meta_json(const std::string &api_path,
|
||||
json &json_data) const -> api_error {
|
||||
std::string value;
|
||||
const auto res = perform_action(__FUNCTION__, [&]() -> rocksdb::Status {
|
||||
return db_->Get(rocksdb::ReadOptions(), default_family_, api_path, &value);
|
||||
});
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
json_data = json::parse(value);
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto meta_db::get_item_meta(const std::string &api_path,
|
||||
api_meta_map &meta) const -> api_error {
|
||||
json json_data;
|
||||
const auto ret = get_item_meta_json(api_path, json_data);
|
||||
if (ret == api_error::success) {
|
||||
for (auto it = json_data.begin(); it != json_data.end(); it++) {
|
||||
meta[it.key()] = it.value().get<std::string>();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto meta_db::get_item_meta(const std::string &api_path, const std::string &key,
|
||||
std::string &value) const -> api_error {
|
||||
json json_data;
|
||||
const auto ret = get_item_meta_json(api_path, json_data);
|
||||
if (ret == api_error::success) {
|
||||
if (json_data.find(key) != json_data.end()) {
|
||||
value = json_data[key].get<std::string>();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto meta_db::get_item_meta_exists(const std::string &api_path) const -> bool {
|
||||
std::string value;
|
||||
return db_->Get(rocksdb::ReadOptions(), api_path, &value).ok();
|
||||
}
|
||||
|
||||
auto meta_db::get_pinned_files() const -> std::vector<std::string> {
|
||||
std::vector<std::string> ret;
|
||||
|
||||
auto iterator = const_cast<meta_db *>(this)->create_iterator(false);
|
||||
for (iterator->SeekToFirst(); iterator->Valid(); iterator->Next()) {
|
||||
auto api_path = iterator->key().ToString();
|
||||
std::string pinned;
|
||||
const auto res = get_item_meta(api_path, META_PINNED, pinned);
|
||||
if ((res == api_error::success) && not pinned.empty() &&
|
||||
utils::string::to_bool(pinned)) {
|
||||
ret.emplace_back(api_path);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto meta_db::get_source_path_exists(const std::string &source_path) const
|
||||
-> bool {
|
||||
std::string value;
|
||||
return db_->Get(rocksdb::ReadOptions(), source_family_, source_path, &value)
|
||||
.ok();
|
||||
}
|
||||
|
||||
auto meta_db::perform_action(
|
||||
const std::string &function_name,
|
||||
const std::function<rocksdb::Status()> &action) const -> api_error {
|
||||
const 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 meta_db::get_total_item_count() const -> std::uint64_t {
|
||||
std::uint64_t ret = 0u;
|
||||
auto iter = create_iterator(false);
|
||||
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
||||
ret++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto meta_db::remove_item_meta(const std::string &api_path) -> api_error {
|
||||
json json_data;
|
||||
auto res = get_item_meta_json(api_path, json_data);
|
||||
if (res != api_error::success) {
|
||||
return res == api_error::item_not_found ? api_error::success : res;
|
||||
}
|
||||
|
||||
if (not json_data[META_KEY].empty()) {
|
||||
if ((res = perform_action(__FUNCTION__, [&]() -> rocksdb::Status {
|
||||
return db_->Delete(rocksdb::WriteOptions(), keys_family_,
|
||||
json_data[META_KEY].get<std::string>());
|
||||
})) != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
if (not json_data[META_SOURCE].empty()) {
|
||||
if ((res = perform_action(__FUNCTION__, [&]() -> rocksdb::Status {
|
||||
return db_->Delete(rocksdb::WriteOptions(), source_family_,
|
||||
json_data[META_SOURCE].get<std::string>());
|
||||
})) != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return perform_action(__FUNCTION__, [&]() -> rocksdb::Status {
|
||||
return db_->Delete(rocksdb::WriteOptions(), default_family_, api_path);
|
||||
});
|
||||
}
|
||||
|
||||
auto meta_db::remove_item_meta(const std::string &api_path,
|
||||
const std::string &key) -> api_error {
|
||||
json json_data;
|
||||
auto res = get_item_meta_json(api_path, json_data);
|
||||
if (res != api_error::success) {
|
||||
return res == api_error::item_not_found ? api_error::success : res;
|
||||
}
|
||||
|
||||
if ((key == META_KEY) && not json_data[META_KEY].empty()) {
|
||||
if ((res = perform_action(__FUNCTION__, [&]() -> rocksdb::Status {
|
||||
return db_->Delete(rocksdb::WriteOptions(), keys_family_,
|
||||
json_data[META_KEY].get<std::string>());
|
||||
})) != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
if ((key == META_SOURCE) && not json_data[META_SOURCE].empty()) {
|
||||
if ((res = perform_action(__FUNCTION__, [&]() -> rocksdb::Status {
|
||||
return db_->Delete(rocksdb::WriteOptions(), source_family_,
|
||||
json_data[META_SOURCE].get<std::string>());
|
||||
})) != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
json_data.erase(key);
|
||||
return perform_action(__FUNCTION__, [&]() -> rocksdb::Status {
|
||||
return db_->Put(rocksdb::WriteOptions(), default_family_, api_path,
|
||||
json_data.dump());
|
||||
});
|
||||
}
|
||||
|
||||
auto meta_db::rename_item_meta(const std::string &source_path,
|
||||
const std::string &from_api_path,
|
||||
const std::string &to_api_path) -> api_error {
|
||||
api_meta_map meta{};
|
||||
auto res = get_item_meta(from_api_path, meta);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if ((res = remove_item_meta(from_api_path)) != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (not source_path.empty()) {
|
||||
meta[META_SOURCE] = source_path;
|
||||
}
|
||||
|
||||
return set_item_meta(to_api_path, meta);
|
||||
}
|
||||
|
||||
auto meta_db::set_item_meta(const std::string &api_path, const std::string &key,
|
||||
const std::string &value) -> api_error {
|
||||
if (key == META_SOURCE) {
|
||||
return set_source_path(api_path, value);
|
||||
}
|
||||
|
||||
if (key == META_KEY) {
|
||||
const auto res = remove_item_meta(api_path, META_KEY);
|
||||
if ((res != api_error::success) && (res != api_error::item_not_found)) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
auto res = store_item_meta(api_path, key, value);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (key == META_KEY) {
|
||||
return perform_action(__FUNCTION__, [&]() -> rocksdb::Status {
|
||||
return db_->Put(rocksdb::WriteOptions(), keys_family_, value, api_path);
|
||||
});
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto meta_db::set_item_meta(const std::string &api_path,
|
||||
const api_meta_map &meta) -> api_error {
|
||||
auto ret = api_error::success;
|
||||
auto it = meta.begin();
|
||||
for (std::size_t i = 0u; (ret == api_error::success) && (i < meta.size());
|
||||
i++) {
|
||||
ret = set_item_meta(api_path, it->first, it->second);
|
||||
it++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto meta_db::set_source_path(const std::string &api_path,
|
||||
const std::string &source_path) -> api_error {
|
||||
std::string current_source_path;
|
||||
auto res = get_item_meta(api_path, META_SOURCE, current_source_path);
|
||||
if ((res != api_error::success) && (res != api_error::item_not_found)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
// TODO multiple db ops should be in transaction
|
||||
if (not current_source_path.empty()) {
|
||||
if ((res = perform_action(__FUNCTION__, [&]() -> rocksdb::Status {
|
||||
return db_->Delete(rocksdb::WriteOptions(), source_family_,
|
||||
current_source_path);
|
||||
})) != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
if (not source_path.empty()) {
|
||||
if ((res = perform_action(__FUNCTION__, [&]() -> rocksdb::Status {
|
||||
return db_->Put(rocksdb::WriteOptions(), source_family_, source_path,
|
||||
api_path);
|
||||
})) != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return store_item_meta(api_path, META_SOURCE, source_path);
|
||||
}
|
||||
|
||||
auto meta_db::store_item_meta(const std::string &api_path,
|
||||
const std::string &key, const std::string &value)
|
||||
-> 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;
|
||||
}
|
||||
|
||||
json_data[key] = value;
|
||||
return perform_action(__FUNCTION__, [&]() -> rocksdb::Status {
|
||||
return db_->Put(rocksdb::WriteOptions(), default_family_, api_path,
|
||||
json_data.dump());
|
||||
});
|
||||
}
|
||||
} // namespace repertory
|
@ -60,7 +60,8 @@ api_error fuse_drive::chflags_impl(std::string api_path, uint32_t flags) {
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto fuse_drive::chmod_impl(std::string api_path, mode_t mode,
|
||||
struct fuse_file_info * /*fi*/) -> api_error {
|
||||
struct fuse_file_info * /*file_info*/)
|
||||
-> api_error {
|
||||
#else
|
||||
auto fuse_drive::chmod_impl(std::string api_path, mode_t mode) -> api_error {
|
||||
#endif
|
||||
@ -71,7 +72,8 @@ auto fuse_drive::chmod_impl(std::string api_path, mode_t mode) -> api_error {
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid,
|
||||
struct fuse_file_info * /*fi*/) -> api_error {
|
||||
struct fuse_file_info * /*file_info*/)
|
||||
-> api_error {
|
||||
#else
|
||||
auto fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid)
|
||||
-> api_error {
|
||||
@ -96,16 +98,18 @@ auto fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid)
|
||||
}
|
||||
|
||||
auto fuse_drive::create_impl(std::string api_path, mode_t mode,
|
||||
struct fuse_file_info *fi) -> api_error {
|
||||
fi->fh = 0u;
|
||||
struct fuse_file_info *file_info) -> api_error {
|
||||
file_info->fh = 0U;
|
||||
|
||||
const auto is_directory_op = ((fi->flags & O_DIRECTORY) == O_DIRECTORY);
|
||||
const auto is_create_op = ((fi->flags & O_CREAT) == O_CREAT);
|
||||
const auto is_truncate_op =
|
||||
((fi->flags & O_TRUNC) &&
|
||||
((fi->flags & O_WRONLY) || (fi->flags & O_RDWR)));
|
||||
const auto is_directory_op =
|
||||
((file_info->flags & O_DIRECTORY) == O_DIRECTORY);
|
||||
const auto is_create_op = ((file_info->flags & O_CREAT) == O_CREAT);
|
||||
const auto is_truncate_op = (((file_info->flags & O_TRUNC) != 0) &&
|
||||
(((file_info->flags & O_WRONLY) != 0) ||
|
||||
((file_info->flags & O_RDWR) != 0)));
|
||||
|
||||
if ((fi->flags & O_WRONLY) || (fi->flags & O_RDWR)) {
|
||||
if (((file_info->flags & O_WRONLY) != 0) ||
|
||||
((file_info->flags & O_RDWR) != 0)) {
|
||||
const auto res = provider_.is_file_writeable(api_path)
|
||||
? api_error::success
|
||||
: api_error::permission_denied;
|
||||
@ -154,42 +158,41 @@ auto fuse_drive::create_impl(std::string api_path, mode_t mode,
|
||||
}
|
||||
}
|
||||
|
||||
std::uint64_t handle = 0u;
|
||||
std::shared_ptr<i_open_file> f;
|
||||
std::uint64_t handle{};
|
||||
std::shared_ptr<i_open_file> open_file;
|
||||
if (is_create_op) {
|
||||
const auto now = utils::get_file_time_now();
|
||||
#ifdef __APPLE__
|
||||
const auto osx_flags = static_cast<std::uint32_t>(fi->flags);
|
||||
const auto osx_flags = static_cast<std::uint32_t>(file_info->flags);
|
||||
#else
|
||||
const auto osx_flags = std::uint32_t(0u);
|
||||
const auto osx_flags = 0U;
|
||||
#endif
|
||||
|
||||
auto meta = create_meta_attributes(
|
||||
now, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE, now, now,
|
||||
is_directory_op, "", get_effective_gid(), "", mode, now, 0u, osx_flags,
|
||||
0u,
|
||||
is_directory_op, get_effective_gid(), "", mode, now, 0U, osx_flags, 0U,
|
||||
utils::path::combine(config_.get_cache_directory(),
|
||||
{utils::create_uuid_string()}),
|
||||
get_effective_uid(), now);
|
||||
|
||||
res = fm_->create(api_path, meta, fi->flags, handle, f);
|
||||
res = fm_->create(api_path, meta, file_info->flags, handle, open_file);
|
||||
if ((res != api_error::item_exists) && (res != api_error::success)) {
|
||||
return res;
|
||||
}
|
||||
} else if (((res = fm_->open(api_path, is_directory_op, fi->flags, handle,
|
||||
f)) != api_error::success)) {
|
||||
} else if (((res = fm_->open(api_path, is_directory_op, file_info->flags,
|
||||
handle, open_file)) != api_error::success)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
fi->fh = handle;
|
||||
file_info->fh = handle;
|
||||
if (is_truncate_op) {
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
if ((res = truncate_impl(api_path, 0, fi)) != api_error::success) {
|
||||
if ((res = truncate_impl(api_path, 0, file_info)) != api_error::success) {
|
||||
#else
|
||||
if ((res = ftruncate_impl(api_path, 0, fi)) != api_error::success) {
|
||||
if ((res = ftruncate_impl(api_path, 0, file_info)) != api_error::success) {
|
||||
#endif
|
||||
fm_->close(handle);
|
||||
fi->fh = 0u;
|
||||
file_info->fh = 0U;
|
||||
errno = std::abs(utils::from_api_error(res));
|
||||
return res;
|
||||
}
|
||||
@ -198,7 +201,7 @@ auto fuse_drive::create_impl(std::string api_path, mode_t mode,
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
void fuse_drive::destroy_impl(void *) {
|
||||
void fuse_drive::destroy_impl(void * /* ptr */) {
|
||||
event_system::instance().raise<drive_unmount_pending>(get_mount_location());
|
||||
|
||||
remote_server_.reset();
|
||||
@ -240,21 +243,21 @@ void fuse_drive::destroy_impl(void *) {
|
||||
|
||||
auto fuse_drive::fallocate_impl(std::string /*api_path*/, int mode,
|
||||
off_t offset, off_t length,
|
||||
struct fuse_file_info *fi) -> api_error {
|
||||
std::shared_ptr<i_open_file> f;
|
||||
if (not fm_->get_open_file(fi->fh, true, f)) {
|
||||
struct fuse_file_info *file_info) -> api_error {
|
||||
std::shared_ptr<i_open_file> open_file;
|
||||
if (not fm_->get_open_file(file_info->fh, true, open_file)) {
|
||||
return api_error::invalid_handle;
|
||||
}
|
||||
|
||||
auto res =
|
||||
check_writeable(f->get_open_data(fi->fh), api_error::invalid_handle);
|
||||
auto res = check_writeable(open_file->get_open_data(file_info->fh),
|
||||
api_error::invalid_handle);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if ((res = check_open_flags(f->get_open_data(fi->fh), O_WRONLY | O_APPEND,
|
||||
api_error::invalid_handle)) !=
|
||||
api_error::success) {
|
||||
if ((res = check_open_flags(
|
||||
open_file->get_open_data(file_info->fh), O_WRONLY | O_APPEND,
|
||||
api_error::invalid_handle)) != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -294,13 +297,14 @@ auto fuse_drive::fallocate_impl(std::string /*api_path*/, int mode,
|
||||
};
|
||||
#endif // __APPLE__
|
||||
|
||||
return f->native_operation(offset + length, allocator);
|
||||
return open_file->native_operation(
|
||||
static_cast<std::uint64_t>(offset + length), allocator);
|
||||
}
|
||||
|
||||
auto fuse_drive::fgetattr_impl(std::string api_path, struct stat *st,
|
||||
struct fuse_file_info *fi) -> api_error {
|
||||
std::shared_ptr<i_open_file> f;
|
||||
if (not fm_->get_open_file(fi->fh, false, f)) {
|
||||
struct fuse_file_info *file_info) -> api_error {
|
||||
std::shared_ptr<i_open_file> open_file;
|
||||
if (not fm_->get_open_file(file_info->fh, false, open_file)) {
|
||||
return api_error::invalid_handle;
|
||||
}
|
||||
|
||||
@ -315,17 +319,18 @@ auto fuse_drive::fgetattr_impl(std::string api_path, struct stat *st,
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
fuse_drive_base::populate_stat(api_path, f->get_file_size(), meta, directory,
|
||||
provider_, st);
|
||||
fuse_drive_base::populate_stat(api_path, open_file->get_file_size(), meta,
|
||||
directory, provider_, st);
|
||||
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
auto fuse_drive::fsetattr_x_impl(std::string api_path, struct setattr_x *attr,
|
||||
struct fuse_file_info *fi) -> api_error {
|
||||
struct fuse_file_info *file_info)
|
||||
-> api_error {
|
||||
std::shared_ptr<i_open_file> f;
|
||||
if (not fm_->get_open_file(fi->fh, false, f)) {
|
||||
if (not fm_->get_open_file(file_info->fh, false, f)) {
|
||||
return api_error::invalid_handle;
|
||||
}
|
||||
|
||||
@ -334,13 +339,13 @@ auto fuse_drive::fsetattr_x_impl(std::string api_path, struct setattr_x *attr,
|
||||
#endif // __APPLE__
|
||||
|
||||
auto fuse_drive::fsync_impl(std::string /*api_path*/, int datasync,
|
||||
struct fuse_file_info *fi) -> api_error {
|
||||
std::shared_ptr<i_open_file> f;
|
||||
if (not fm_->get_open_file(fi->fh, false, f)) {
|
||||
struct fuse_file_info *file_info) -> api_error {
|
||||
std::shared_ptr<i_open_file> open_file;
|
||||
if (not fm_->get_open_file(file_info->fh, false, open_file)) {
|
||||
return api_error::invalid_handle;
|
||||
}
|
||||
|
||||
return f->native_operation([&datasync](int handle) -> api_error {
|
||||
return open_file->native_operation([&datasync](int handle) -> api_error {
|
||||
if (handle != REPERTORY_INVALID_HANDLE) {
|
||||
#ifdef __APPLE__
|
||||
if ((datasync ? fcntl(handle, F_FULLFSYNC) : fsync(handle)) == -1) {
|
||||
@ -356,14 +361,14 @@ auto fuse_drive::fsync_impl(std::string /*api_path*/, int datasync,
|
||||
|
||||
#if FUSE_USE_VERSION < 30
|
||||
api_error fuse_drive::ftruncate_impl(std::string /*api_path*/, off_t size,
|
||||
struct fuse_file_info *fi) {
|
||||
struct fuse_file_info *file_info) {
|
||||
std::shared_ptr<i_open_file> f;
|
||||
if (not fm_->get_open_file(fi->fh, true, f)) {
|
||||
if (not fm_->get_open_file(file_info->fh, true, f)) {
|
||||
return api_error::invalid_handle;
|
||||
}
|
||||
|
||||
const auto res =
|
||||
check_writeable(f->get_open_data(fi->fh), api_error::invalid_handle);
|
||||
const auto res = check_writeable(f->get_open_data(file_info->fh),
|
||||
api_error::invalid_handle);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
@ -379,14 +384,14 @@ 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
|
||||
-> directory_item_list {
|
||||
directory_item_list di{};
|
||||
auto res = provider_.get_directory_items(api_path, di);
|
||||
directory_item_list list{};
|
||||
auto res = provider_.get_directory_items(api_path, list);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res,
|
||||
"failed to get directory items");
|
||||
}
|
||||
|
||||
return di;
|
||||
return list;
|
||||
}
|
||||
|
||||
auto fuse_drive::get_file_size(const std::string &api_path) const
|
||||
@ -420,7 +425,8 @@ auto fuse_drive::get_item_meta(const std::string &api_path,
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto fuse_drive::getattr_impl(std::string api_path, struct stat *st,
|
||||
struct fuse_file_info * /*fi*/) -> api_error {
|
||||
struct fuse_file_info * /*file_info*/)
|
||||
-> api_error {
|
||||
#else
|
||||
auto fuse_drive::getattr_impl(std::string api_path, struct stat *st)
|
||||
-> api_error {
|
||||
@ -434,11 +440,11 @@ auto fuse_drive::getattr_impl(std::string api_path, struct stat *st)
|
||||
|
||||
auto found = false;
|
||||
directory_cache_->execute_action(parent, [&](directory_iterator &iter) {
|
||||
directory_item di{};
|
||||
if ((found =
|
||||
(iter.get_directory_item(api_path, di) == api_error::success))) {
|
||||
fuse_drive_base::populate_stat(api_path, di.size, di.meta, di.directory,
|
||||
provider_, st);
|
||||
directory_item dir_item{};
|
||||
if ((found = (iter.get_directory_item(api_path, dir_item) ==
|
||||
api_error::success))) {
|
||||
fuse_drive_base::populate_stat(api_path, dir_item.size, dir_item.meta,
|
||||
dir_item.directory, provider_, st);
|
||||
}
|
||||
});
|
||||
|
||||
@ -582,9 +588,9 @@ auto fuse_drive::mkdir_impl(std::string api_path, mode_t mode) -> api_error {
|
||||
}
|
||||
|
||||
const auto now = utils::get_file_time_now();
|
||||
auto meta = create_meta_attributes(
|
||||
now, FILE_ATTRIBUTE_DIRECTORY, now, now, true, "", get_effective_gid(),
|
||||
"", mode, now, 0u, 0u, 0u, "", get_effective_uid(), now);
|
||||
auto meta = create_meta_attributes(now, FILE_ATTRIBUTE_DIRECTORY, now, now,
|
||||
true, get_effective_gid(), "", mode, now,
|
||||
0U, 0U, 0U, "", get_effective_uid(), now);
|
||||
if ((res = provider_.create_directory(api_path, meta)) !=
|
||||
api_error::success) {
|
||||
return res;
|
||||
@ -611,15 +617,16 @@ void fuse_drive::notify_fuse_main_exit(int &ret) {
|
||||
}
|
||||
}
|
||||
|
||||
auto fuse_drive::open_impl(std::string api_path, struct fuse_file_info *fi)
|
||||
-> api_error {
|
||||
fi->flags &= (~O_CREAT);
|
||||
return create_impl(api_path, 0, fi);
|
||||
auto fuse_drive::open_impl(std::string api_path,
|
||||
struct fuse_file_info *file_info) -> api_error {
|
||||
file_info->flags &= (~O_CREAT);
|
||||
return create_impl(api_path, 0, file_info);
|
||||
}
|
||||
|
||||
auto fuse_drive::opendir_impl(std::string api_path, struct fuse_file_info *fi)
|
||||
-> api_error {
|
||||
const auto mask = (O_RDONLY != (fi->flags & O_ACCMODE) ? W_OK : R_OK) | X_OK;
|
||||
auto fuse_drive::opendir_impl(std::string api_path,
|
||||
struct fuse_file_info *file_info) -> api_error {
|
||||
const auto mask =
|
||||
(O_RDONLY != (file_info->flags & O_ACCMODE) ? W_OK : R_OK) | X_OK;
|
||||
auto res = check_access(api_path, mask);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
@ -638,35 +645,36 @@ auto fuse_drive::opendir_impl(std::string api_path, struct fuse_file_info *fi)
|
||||
return api_error::directory_not_found;
|
||||
}
|
||||
|
||||
directory_item_list dl{};
|
||||
if ((res = provider_.get_directory_items(api_path, dl)) !=
|
||||
directory_item_list list{};
|
||||
if ((res = provider_.get_directory_items(api_path, list)) !=
|
||||
api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
auto *iter = new directory_iterator(std::move(dl));
|
||||
fi->fh = reinterpret_cast<std::uint64_t>(iter);
|
||||
auto *iter = new directory_iterator(std::move(list));
|
||||
file_info->fh = reinterpret_cast<std::uint64_t>(iter);
|
||||
directory_cache_->set_directory(api_path, iter);
|
||||
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
void fuse_drive::populate_stat(const directory_item &di,
|
||||
void fuse_drive::populate_stat(const directory_item &dir_item,
|
||||
struct stat &st) const {
|
||||
fuse_drive_base::populate_stat(di.api_path, di.size, di.meta, di.directory,
|
||||
provider_, &st);
|
||||
fuse_drive_base::populate_stat(dir_item.api_path, dir_item.size,
|
||||
dir_item.meta, dir_item.directory, provider_,
|
||||
&st);
|
||||
}
|
||||
|
||||
auto fuse_drive::read_impl(std::string api_path, char *buffer, size_t read_size,
|
||||
off_t read_offset, struct fuse_file_info *fi,
|
||||
off_t read_offset, struct fuse_file_info *file_info,
|
||||
std::size_t &bytes_read) -> api_error {
|
||||
std::shared_ptr<i_open_file> f;
|
||||
if (not fm_->get_open_file(fi->fh, false, f)) {
|
||||
std::shared_ptr<i_open_file> open_file;
|
||||
if (not fm_->get_open_file(file_info->fh, false, open_file)) {
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
auto res =
|
||||
check_readable(f->get_open_data(fi->fh), api_error::invalid_handle);
|
||||
auto res = check_readable(open_file->get_open_data(file_info->fh),
|
||||
api_error::invalid_handle);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
@ -675,11 +683,12 @@ auto fuse_drive::read_impl(std::string api_path, char *buffer, size_t read_size,
|
||||
// __FUNCTION__, api_path, std::to_string(read_size) + ':' +
|
||||
// std::to_string(read_offset));
|
||||
data_buffer data;
|
||||
res = f->read(read_size, static_cast<std::uint64_t>(read_offset), data);
|
||||
res =
|
||||
open_file->read(read_size, static_cast<std::uint64_t>(read_offset), data);
|
||||
// event_system::instance().raise<debug_log>(
|
||||
// __FUNCTION__, api_path, std::to_string(bytes_read) + ':' +
|
||||
// api_error_to_string(res));
|
||||
if ((bytes_read = data.size())) {
|
||||
if ((bytes_read = data.size()) != 0U) {
|
||||
std::memcpy(buffer, data.data(), data.size());
|
||||
data.clear();
|
||||
update_accessed_time(api_path);
|
||||
@ -691,20 +700,20 @@ auto fuse_drive::read_impl(std::string api_path, char *buffer, size_t read_size,
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto fuse_drive::readdir_impl(std::string api_path, void *buf,
|
||||
fuse_fill_dir_t fuse_fill_dir, off_t offset,
|
||||
struct fuse_file_info *fi,
|
||||
struct fuse_file_info *file_info,
|
||||
fuse_readdir_flags /*flags*/) -> api_error {
|
||||
#else
|
||||
auto fuse_drive::readdir_impl(std::string api_path, void *buf,
|
||||
fuse_fill_dir_t fuse_fill_dir, off_t offset,
|
||||
struct fuse_file_info *fi) -> api_error {
|
||||
struct fuse_file_info *file_info) -> api_error {
|
||||
#endif
|
||||
auto res = check_access(api_path, X_OK);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
auto *iter = reinterpret_cast<directory_iterator *>(fi->fh);
|
||||
if (not iter) {
|
||||
auto *iter = reinterpret_cast<directory_iterator *>(file_info->fh);
|
||||
if (iter == nullptr) {
|
||||
return api_error::invalid_handle;
|
||||
}
|
||||
|
||||
@ -730,15 +739,16 @@ auto fuse_drive::readdir_impl(std::string api_path, void *buf,
|
||||
}
|
||||
|
||||
auto fuse_drive::release_impl(std::string /*api_path*/,
|
||||
struct fuse_file_info *fi) -> api_error {
|
||||
fm_->close(fi->fh);
|
||||
struct fuse_file_info *file_info) -> api_error {
|
||||
fm_->close(file_info->fh);
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto fuse_drive::releasedir_impl(std::string /*api_path*/,
|
||||
struct fuse_file_info *fi) -> api_error {
|
||||
auto *iter = reinterpret_cast<directory_iterator *>(fi->fh);
|
||||
if (not iter) {
|
||||
struct fuse_file_info *file_info)
|
||||
-> api_error {
|
||||
auto *iter = reinterpret_cast<directory_iterator *>(file_info->fh);
|
||||
if (iter == nullptr) {
|
||||
return api_error::invalid_handle;
|
||||
}
|
||||
|
||||
@ -808,9 +818,7 @@ auto fuse_drive::rmdir_impl(std::string api_path) -> api_error {
|
||||
}
|
||||
|
||||
auto *iter = directory_cache_->remove_directory(api_path);
|
||||
if (iter) {
|
||||
delete iter;
|
||||
}
|
||||
delete iter;
|
||||
|
||||
return api_error::success;
|
||||
}
|
||||
@ -841,10 +849,10 @@ auto fuse_drive::getxattr_common(std::string api_path, const char *name,
|
||||
directory_cache_->execute_action(
|
||||
utils::path::get_parent_api_path(api_path),
|
||||
[&](directory_iterator &iterator) {
|
||||
directory_item di{};
|
||||
if ((found = (iterator.get_directory_item(api_path, di) ==
|
||||
directory_item dir_item{};
|
||||
if ((found = (iterator.get_directory_item(api_path, dir_item) ==
|
||||
api_error::success))) {
|
||||
meta = di.meta;
|
||||
meta = dir_item.meta;
|
||||
}
|
||||
});
|
||||
|
||||
@ -853,13 +861,13 @@ auto fuse_drive::getxattr_common(std::string api_path, const char *name,
|
||||
res = api_error::xattr_not_found;
|
||||
if (meta.find(attribute_name) != meta.end()) {
|
||||
const auto data = macaron::Base64::Decode(meta[attribute_name]);
|
||||
if (not position || (*position < data.size())) {
|
||||
if ((position == nullptr) || (*position < data.size())) {
|
||||
res = api_error::success;
|
||||
attribute_size = static_cast<int>(data.size());
|
||||
if (size) {
|
||||
if (size != 0U) {
|
||||
res = api_error::xattr_buffer_small;
|
||||
if (size >= data.size()) {
|
||||
memcpy(value, &data[0], data.size());
|
||||
memcpy(value, data.data(), data.size());
|
||||
return api_error::success;
|
||||
}
|
||||
}
|
||||
@ -897,13 +905,13 @@ auto fuse_drive::listxattr_impl(std::string api_path, char *buffer, size_t size,
|
||||
|
||||
api_meta_map meta;
|
||||
if ((res = provider_.get_item_meta(api_path, meta)) == api_error::success) {
|
||||
for (const auto &kv : meta) {
|
||||
if (utils::collection_excludes(META_USED_NAMES, kv.first)) {
|
||||
auto attribute_name = kv.first;
|
||||
for (const auto &meta_item : meta) {
|
||||
if (utils::collection_excludes(META_USED_NAMES, meta_item.first)) {
|
||||
auto attribute_name = meta_item.first;
|
||||
#ifdef __APPLE__
|
||||
if (attribute_name != G_KAUTH_FILESEC_XATTR) {
|
||||
#endif
|
||||
const auto attribute_name_size = strlen(attribute_name.c_str()) + 1u;
|
||||
const auto attribute_name_size = strlen(attribute_name.c_str()) + 1U;
|
||||
if (size >= attribute_name_size) {
|
||||
strncpy(&buffer[required_size], attribute_name.c_str(),
|
||||
attribute_name_size);
|
||||
@ -912,7 +920,7 @@ auto fuse_drive::listxattr_impl(std::string api_path, char *buffer, size_t size,
|
||||
res = api_error::xattr_buffer_small;
|
||||
}
|
||||
|
||||
required_size += attribute_name_size;
|
||||
required_size += static_cast<int>(attribute_name_size);
|
||||
#ifdef __APPLE__
|
||||
}
|
||||
#endif
|
||||
@ -972,7 +980,7 @@ auto fuse_drive::setxattr_impl(std::string api_path, const char *name,
|
||||
|
||||
const auto attribute_namespace =
|
||||
utils::string::contains(attribute_name, ".")
|
||||
? utils::string::split(attribute_name, '.', false)[0u]
|
||||
? utils::string::split(attribute_name, '.', false)[0U]
|
||||
: "";
|
||||
if ((attribute_name.size() > XATTR_NAME_MAX) || (size > XATTR_SIZE_MAX)) {
|
||||
return api_error::xattr_too_big;
|
||||
@ -1192,7 +1200,7 @@ auto fuse_drive::statfs_x_impl(std::string /*api_path*/, struct statfs *stbuf)
|
||||
#else // __APPLE__
|
||||
auto fuse_drive::statfs_impl(std::string /*api_path*/, struct statvfs *stbuf)
|
||||
-> api_error {
|
||||
if (statvfs(&config_.get_cache_directory()[0], stbuf) != 0) {
|
||||
if (statvfs(config_.get_cache_directory().data(), stbuf) != 0) {
|
||||
return api_error::os_error;
|
||||
}
|
||||
|
||||
@ -1204,7 +1212,7 @@ auto fuse_drive::statfs_impl(std::string /*api_path*/, struct statvfs *stbuf)
|
||||
stbuf->f_blocks = utils::divide_with_ceiling(
|
||||
total_bytes, static_cast<std::uint64_t>(stbuf->f_frsize));
|
||||
stbuf->f_bavail = stbuf->f_bfree =
|
||||
stbuf->f_blocks ? (stbuf->f_blocks - used_blocks) : 0;
|
||||
stbuf->f_blocks == 0U ? 0 : (stbuf->f_blocks - used_blocks);
|
||||
stbuf->f_ffree = stbuf->f_favail =
|
||||
stbuf->f_files - provider_.get_total_item_count();
|
||||
|
||||
@ -1214,7 +1222,8 @@ auto fuse_drive::statfs_impl(std::string /*api_path*/, struct statvfs *stbuf)
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto fuse_drive::truncate_impl(std::string api_path, off_t size,
|
||||
struct fuse_file_info * /*fi*/) -> api_error {
|
||||
struct fuse_file_info * /*file_info*/)
|
||||
-> api_error {
|
||||
#else
|
||||
auto fuse_drive::truncate_impl(std::string api_path, off_t size) -> api_error {
|
||||
#endif
|
||||
@ -1234,9 +1243,9 @@ auto fuse_drive::truncate_impl(std::string api_path, off_t size) -> api_error {
|
||||
}
|
||||
|
||||
open_file_data ofd = O_RDWR;
|
||||
std::uint64_t handle = 0u;
|
||||
std::shared_ptr<i_open_file> f;
|
||||
if ((res = fm_->open(api_path, false, ofd, handle, f)) !=
|
||||
std::uint64_t handle{};
|
||||
std::shared_ptr<i_open_file> open_file;
|
||||
if ((res = fm_->open(api_path, false, ofd, handle, open_file)) !=
|
||||
api_error::success) {
|
||||
return res;
|
||||
}
|
||||
@ -1246,7 +1255,7 @@ auto fuse_drive::truncate_impl(std::string api_path, off_t size) -> api_error {
|
||||
return err;
|
||||
};
|
||||
|
||||
return cleanup(f->resize(size));
|
||||
return cleanup(open_file->resize(static_cast<std::uint64_t>(size)));
|
||||
}
|
||||
|
||||
auto fuse_drive::unlink_impl(std::string api_path) -> api_error {
|
||||
@ -1269,7 +1278,8 @@ auto fuse_drive::unlink_impl(std::string api_path) -> api_error {
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
auto fuse_drive::utimens_impl(std::string api_path, const struct timespec tv[2],
|
||||
struct fuse_file_info * /*fi*/) -> api_error {
|
||||
struct fuse_file_info * /*file_info*/)
|
||||
-> api_error {
|
||||
#else
|
||||
auto fuse_drive::utimens_impl(std::string api_path, const struct timespec tv[2])
|
||||
-> api_error {
|
||||
@ -1285,17 +1295,17 @@ auto fuse_drive::utimens_impl(std::string api_path, const struct timespec tv[2])
|
||||
}
|
||||
|
||||
meta.clear();
|
||||
if (not tv || (tv[0].tv_nsec == UTIME_NOW)) {
|
||||
if ((tv == nullptr) || (tv[0U].tv_nsec == UTIME_NOW)) {
|
||||
meta[META_ACCESSED] = std::to_string(utils::get_file_time_now());
|
||||
} else if (tv[0].tv_nsec != UTIME_OMIT) {
|
||||
const auto val = tv[0].tv_nsec + (tv[0].tv_sec * NANOS_PER_SECOND);
|
||||
} else if (tv[0U].tv_nsec != UTIME_OMIT) {
|
||||
const auto val = tv[0U].tv_nsec + (tv[0U].tv_sec * NANOS_PER_SECOND);
|
||||
meta[META_ACCESSED] = std::to_string(val);
|
||||
}
|
||||
|
||||
if (not tv || (tv[1].tv_nsec == UTIME_NOW)) {
|
||||
if ((tv == nullptr) || (tv[1U].tv_nsec == UTIME_NOW)) {
|
||||
meta[META_MODIFIED] = std::to_string(utils::get_file_time_now());
|
||||
} else if (tv[1].tv_nsec != UTIME_OMIT) {
|
||||
const auto val = tv[1].tv_nsec + (tv[1].tv_sec * NANOS_PER_SECOND);
|
||||
} else if (tv[1U].tv_nsec != UTIME_OMIT) {
|
||||
const auto val = tv[1U].tv_nsec + (tv[1U].tv_sec * NANOS_PER_SECOND);
|
||||
meta[META_MODIFIED] = std::to_string(val);
|
||||
}
|
||||
|
||||
@ -1309,28 +1319,29 @@ auto fuse_drive::utimens_impl(std::string api_path, const struct timespec tv[2])
|
||||
auto fuse_drive::write_impl(std::string /*api_path*/
|
||||
,
|
||||
const char *buffer, size_t write_size,
|
||||
off_t write_offset, struct fuse_file_info *fi,
|
||||
off_t write_offset,
|
||||
struct fuse_file_info *file_info,
|
||||
std::size_t &bytes_written) -> api_error {
|
||||
std::shared_ptr<i_open_file> f;
|
||||
if (not fm_->get_open_file(fi->fh, true, f)) {
|
||||
std::shared_ptr<i_open_file> open_file;
|
||||
if (not fm_->get_open_file(file_info->fh, true, open_file)) {
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
auto res =
|
||||
check_writeable(f->get_open_data(fi->fh), api_error::invalid_handle);
|
||||
auto res = check_writeable(open_file->get_open_data(file_info->fh),
|
||||
api_error::invalid_handle);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (write_size > 0) {
|
||||
if (f->get_open_data(fi->fh) & O_APPEND) {
|
||||
write_offset = f->get_file_size();
|
||||
if ((open_file->get_open_data(file_info->fh) & O_APPEND) != 0) {
|
||||
write_offset = static_cast<off_t>(open_file->get_file_size());
|
||||
}
|
||||
|
||||
data_buffer data(write_size);
|
||||
std::memcpy(&data[0], buffer, write_size);
|
||||
return f->write(static_cast<std::uint64_t>(write_offset), std::move(data),
|
||||
bytes_written);
|
||||
std::memcpy(data.data(), buffer, write_size);
|
||||
return open_file->write(static_cast<std::uint64_t>(write_offset),
|
||||
std::move(data), bytes_written);
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
|
@ -60,8 +60,8 @@ auto remote_fuse_drive::chmod_impl(std::string api_path, mode_t mode,
|
||||
auto remote_fuse_drive::chmod_impl(std::string api_path, mode_t mode)
|
||||
-> api_error {
|
||||
#endif
|
||||
return utils::to_api_error(
|
||||
remote_instance_->fuse_chmod(api_path.c_str(), mode));
|
||||
return utils::to_api_error(remote_instance_->fuse_chmod(
|
||||
api_path.c_str(), static_cast<remote::file_mode>(mode)));
|
||||
}
|
||||
|
||||
#if FUSE_USE_VERSION >= 30
|
||||
@ -79,7 +79,9 @@ auto remote_fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid)
|
||||
auto remote_fuse_drive::create_impl(std::string api_path, mode_t mode,
|
||||
struct fuse_file_info *fi) -> api_error {
|
||||
return utils::to_api_error(remote_instance_->fuse_create(
|
||||
api_path.c_str(), mode, remote::create_open_flags(fi->flags), fi->fh));
|
||||
api_path.c_str(), static_cast<remote::file_mode>(mode),
|
||||
remote::create_open_flags(static_cast<std::uint32_t>(fi->flags)),
|
||||
fi->fh));
|
||||
}
|
||||
|
||||
void remote_fuse_drive::destroy_impl(void * /*ptr*/) {
|
||||
@ -248,8 +250,8 @@ auto remote_fuse_drive::init_impl(struct fuse_conn_info *conn) -> void * {
|
||||
|
||||
auto remote_fuse_drive::mkdir_impl(std::string api_path, mode_t mode)
|
||||
-> api_error {
|
||||
return utils::to_api_error(
|
||||
remote_instance_->fuse_mkdir(api_path.c_str(), mode));
|
||||
return utils::to_api_error(remote_instance_->fuse_mkdir(
|
||||
api_path.c_str(), static_cast<remote::file_mode>(mode)));
|
||||
}
|
||||
|
||||
void remote_fuse_drive::notify_fuse_main_exit(int &ret) {
|
||||
|
@ -166,12 +166,12 @@ void remote_server::populate_stat(const struct stat64 &st1, remote::stat &st) {
|
||||
st.st_mtimespec =
|
||||
st1.st_mtim.tv_nsec + (st1.st_mtim.tv_sec * NANOS_PER_SECOND);
|
||||
#endif
|
||||
st.st_blksize = st1.st_blksize;
|
||||
st.st_blocks = st1.st_blocks;
|
||||
st.st_blksize = static_cast<remote::block_size>(st1.st_blksize);
|
||||
st.st_blocks = static_cast<remote::block_count>(st1.st_blocks);
|
||||
st.st_gid = st1.st_gid;
|
||||
st.st_mode = st1.st_mode;
|
||||
st.st_nlink = st1.st_nlink;
|
||||
st.st_size = st1.st_size;
|
||||
st.st_mode = static_cast<remote::file_mode>(st1.st_mode);
|
||||
st.st_nlink = static_cast<remote::file_nlink>(st1.st_nlink);
|
||||
st.st_size = static_cast<remote::file_size>(st1.st_size);
|
||||
st.st_uid = st1.st_uid;
|
||||
}
|
||||
|
||||
@ -227,9 +227,10 @@ auto remote_server::fuse_create(const char *path, const remote::file_mode &mode,
|
||||
-> packet::error_type {
|
||||
const auto file_path = construct_path(path);
|
||||
const auto res =
|
||||
open(file_path.c_str(), remote::create_os_open_flags(flags), mode);
|
||||
open(file_path.c_str(),
|
||||
static_cast<int>(remote::create_os_open_flags(flags)), mode);
|
||||
if (res >= 0) {
|
||||
handle = res;
|
||||
handle = static_cast<remote::file_handle>(res);
|
||||
set_open_info(res, open_info{0, "", nullptr, file_path});
|
||||
}
|
||||
|
||||
@ -269,13 +270,12 @@ ConstructPath(path); auto ret = HasOpenFileInfo(handle, -EBADF); if (ret == 0) {
|
||||
fstore.fst_offset = offset;
|
||||
fstore.fst_length = length;
|
||||
|
||||
const auto res = fcntl(static_cast<int>(handle), F_PREALLOCATE, &fstore);
|
||||
ret = ((res < 0) ? -errno : 0);
|
||||
const auto res = fcntl(static_cast<native_handle>(handle), F_PREALLOCATE,
|
||||
&fstore); ret = ((res < 0) ? -errno : 0);
|
||||
}
|
||||
#else
|
||||
const auto res = fallocate(static_cast<int>(handle), mode, offset, length);
|
||||
ret = ((res < 0) ? -errno : 0);
|
||||
#endif
|
||||
const auto res = fallocate(static_cast<native_handle>(handle), mode, offset,
|
||||
length); ret = ((res < 0) ? -errno : 0); #endif
|
||||
}
|
||||
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(__FUNCTION__, file_path, ret);
|
||||
@ -289,11 +289,11 @@ auto remote_server::fuse_fgetattr(const char *path, remote::stat &st,
|
||||
const auto file_path = construct_path(path);
|
||||
memset(&st, 0, sizeof(remote::stat));
|
||||
|
||||
auto res = has_open_info(handle, EBADF);
|
||||
auto res = has_open_info(static_cast<native_handle>(handle), EBADF);
|
||||
if (res == 0) {
|
||||
directory = utils::file::is_directory(file_path);
|
||||
struct stat64 st1 {};
|
||||
if ((res = fstat64(static_cast<int>(handle), &st1)) == 0) {
|
||||
if ((res = fstat64(static_cast<native_handle>(handle), &st1)) == 0) {
|
||||
populate_stat(st1, st);
|
||||
}
|
||||
}
|
||||
@ -314,12 +314,12 @@ auto remote_server::fuse_fsetattr_x(const char *path,
|
||||
if (SETATTR_WANTS_MODE(&attr)) {
|
||||
res = (handle == static_cast<std::uint64_t>(REPERTORY_INVALID_HANDLE))
|
||||
? chmod(file_path.c_str(), attr.mode)
|
||||
: fchmod(handle, attr.mode);
|
||||
: fchmod(static_cast<native_handle>(handle), attr.mode);
|
||||
}
|
||||
|
||||
if (res >= 0) {
|
||||
uid_t uid = -1;
|
||||
gid_t gid = -1;
|
||||
auto uid = static_cast<uid_t>(-1);
|
||||
auto gid = static_cast<gid_t>(-1);
|
||||
if (SETATTR_WANTS_UID(&attr)) {
|
||||
uid = attr.uid;
|
||||
}
|
||||
@ -338,7 +338,7 @@ auto remote_server::fuse_fsetattr_x(const char *path,
|
||||
if (SETATTR_WANTS_SIZE(&attr)) {
|
||||
res = (handle == static_cast<std::uint64_t>(REPERTORY_INVALID_HANDLE))
|
||||
? truncate(file_path.c_str(), attr.size)
|
||||
: ftruncate(handle, attr.size);
|
||||
: ftruncate(static_cast<native_handle>(handle), attr.size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -397,14 +397,14 @@ auto remote_server::fuse_fsync(const char *path, const std::int32_t &datasync,
|
||||
-> packet::error_type {
|
||||
const auto file_path = construct_path(path);
|
||||
|
||||
auto res = has_open_info(handle, EBADF);
|
||||
auto res = has_open_info(static_cast<native_handle>(handle), EBADF);
|
||||
if (res == 0) {
|
||||
#ifdef __APPLE__
|
||||
res = datasync ? fcntl(static_cast<int>(handle), F_FULLFSYNC)
|
||||
: fsync(static_cast<int>(handle));
|
||||
res = datasync ? fcntl(static_cast<native_handle>(handle), F_FULLFSYNC)
|
||||
: fsync(static_cast<native_handle>(handle));
|
||||
#else
|
||||
res = datasync ? fdatasync(static_cast<int>(handle))
|
||||
: fsync(static_cast<int>(handle));
|
||||
res = datasync ? fdatasync(static_cast<native_handle>(handle))
|
||||
: fsync(static_cast<native_handle>(handle));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -419,9 +419,9 @@ auto remote_server::fuse_ftruncate(const char *path,
|
||||
-> packet::error_type {
|
||||
const auto file_path = construct_path(path);
|
||||
|
||||
auto res = has_open_info(handle, EBADF);
|
||||
auto res = has_open_info(static_cast<native_handle>(handle), EBADF);
|
||||
if (res == 0) {
|
||||
res = ftruncate(static_cast<int>(handle), size);
|
||||
res = ftruncate(static_cast<native_handle>(handle), size);
|
||||
}
|
||||
|
||||
auto ret = ((res < 0) ? -errno : 0);
|
||||
@ -472,7 +472,7 @@ utils::path::get_parent_api_path(api_path);
|
||||
res = -ENODATA;
|
||||
if (directoryItem.MetaMap.find(name) != directoryItem.MetaMap.end())
|
||||
{ const auto data = macaron::Base64::Decode(directoryItem.MetaMap[name]); res =
|
||||
static_cast<int>(data.size()); if (size) { res = -ERANGE; if (size >=
|
||||
static_cast<native_handle>(data.size()); if (size) { res = -ERANGE; if (size >=
|
||||
data.size()) { memcpy(value, &data[0], data.size()); res = 0;
|
||||
}
|
||||
}
|
||||
@ -561,9 +561,10 @@ auto remote_server::fuse_open(const char *path, const remote::open_flags &flags,
|
||||
remote::file_handle &handle)
|
||||
-> packet::error_type {
|
||||
const auto file_path = construct_path(path);
|
||||
const auto res = open(file_path.c_str(), remote::create_os_open_flags(flags));
|
||||
const auto res = open(file_path.c_str(),
|
||||
static_cast<int>(remote::create_os_open_flags(flags)));
|
||||
if (res >= 0) {
|
||||
handle = res;
|
||||
handle = static_cast<remote::file_handle>(res);
|
||||
set_open_info(res, open_info{0, "", nullptr, file_path});
|
||||
}
|
||||
auto ret = ((res < 0) ? -errno : 0);
|
||||
@ -600,18 +601,21 @@ auto remote_server::fuse_read(const char *path, char *buffer,
|
||||
const remote::file_handle &handle)
|
||||
-> packet::error_type {
|
||||
const auto file_path = construct_path(path);
|
||||
auto &b = *reinterpret_cast<data_buffer *>(buffer);
|
||||
auto res = has_open_info(handle, EBADF);
|
||||
if (res == 0) {
|
||||
b.resize(read_size);
|
||||
res = pread64(static_cast<int>(handle), &b[0], read_size, read_offset);
|
||||
auto &data = *reinterpret_cast<data_buffer *>(buffer);
|
||||
|
||||
ssize_t bytes_read{has_open_info(static_cast<native_handle>(handle), EBADF)};
|
||||
if (bytes_read == 0) {
|
||||
data.resize(read_size);
|
||||
bytes_read = pread64(static_cast<native_handle>(handle), data.data(),
|
||||
read_size, static_cast<off_t>(read_offset));
|
||||
}
|
||||
|
||||
auto ret = ((res < 0) ? -errno : res);
|
||||
auto ret = ((bytes_read < 0) ? -errno : bytes_read);
|
||||
if (ret < 0) {
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(__FUNCTION__, file_path, ret);
|
||||
}
|
||||
return ret;
|
||||
|
||||
return static_cast<packet::error_type>(ret);
|
||||
}
|
||||
|
||||
auto remote_server::fuse_rename(const char *from, const char *to)
|
||||
@ -628,7 +632,7 @@ auto remote_server::fuse_rename(const char *from, const char *to)
|
||||
auto remote_server::fuse_readdir(const char *path,
|
||||
const remote::file_offset &offset,
|
||||
const remote::file_handle &handle,
|
||||
std::string &itemPath) -> packet::error_type {
|
||||
std::string &item_path) -> packet::error_type {
|
||||
const auto file_path = construct_path(path);
|
||||
auto res = 0;
|
||||
if (offset > std::numeric_limits<std::size_t>::max()) {
|
||||
@ -636,8 +640,8 @@ auto remote_server::fuse_readdir(const char *path,
|
||||
res = -1;
|
||||
} else {
|
||||
auto *iterator = reinterpret_cast<directory_iterator *>(handle);
|
||||
if (iterator) {
|
||||
res = iterator->get(static_cast<std::size_t>(offset), itemPath);
|
||||
if (iterator != nullptr) {
|
||||
res = iterator->get(static_cast<std::size_t>(offset), item_path);
|
||||
} else {
|
||||
res = -1;
|
||||
errno = EFAULT;
|
||||
@ -655,10 +659,10 @@ auto remote_server::fuse_release(const char *path,
|
||||
packet::error_type ret = 0;
|
||||
|
||||
const auto file_path = construct_path(path);
|
||||
auto res = has_open_info(handle, EBADF);
|
||||
auto res = has_open_info(static_cast<native_handle>(handle), EBADF);
|
||||
if (res == 0) {
|
||||
res = close(static_cast<int>(handle));
|
||||
remove_open_info(handle);
|
||||
res = close(static_cast<native_handle>(handle));
|
||||
remove_open_info(static_cast<native_handle>(handle));
|
||||
}
|
||||
|
||||
ret = ((res < 0) ? -errno : 0);
|
||||
@ -697,7 +701,7 @@ auto remote_server::fuse_rmdir(const char *path) -> packet::error_type {
|
||||
const auto file_path = construct_path(path);
|
||||
const auto res = rmdir(file_path.c_str());
|
||||
if (res == 0) {
|
||||
auto iterator =
|
||||
auto *iterator =
|
||||
directory_cache_.remove_directory(utils::path::create_api_path(path));
|
||||
if (iterator == nullptr) {
|
||||
utils::error::raise_error(
|
||||
@ -890,16 +894,20 @@ auto remote_server::fuse_write(const char *path, const char *buffer,
|
||||
const remote::file_handle &handle)
|
||||
-> packet::error_type {
|
||||
const auto file_path = construct_path(path);
|
||||
auto res = has_open_info(handle, EBADF);
|
||||
if (res == 0) {
|
||||
res = pwrite64(static_cast<int>(handle), buffer, write_size, write_offset);
|
||||
|
||||
ssize_t bytes_written{
|
||||
has_open_info(static_cast<native_handle>(handle), EBADF)};
|
||||
if (bytes_written == 0) {
|
||||
bytes_written = pwrite64(static_cast<native_handle>(handle), buffer,
|
||||
write_size, static_cast<off_t>(write_offset));
|
||||
}
|
||||
|
||||
auto ret = ((res < 0) ? -errno : res);
|
||||
auto ret = ((bytes_written < 0) ? -errno : bytes_written);
|
||||
if (ret < 0) {
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(__FUNCTION__, file_path, ret);
|
||||
}
|
||||
return ret;
|
||||
|
||||
return static_cast<packet::error_type>(ret);
|
||||
}
|
||||
|
||||
auto remote_server::fuse_write_base64(
|
||||
@ -916,8 +924,10 @@ auto remote_server::winfsp_can_delete(PVOID file_desc, PWSTR file_name)
|
||||
-> packet::error_type {
|
||||
const auto relative_path = utils::string::to_utf8(file_name);
|
||||
const auto file_path = construct_path(relative_path);
|
||||
auto ret = has_open_info(reinterpret_cast<remote::file_handle>(file_desc),
|
||||
STATUS_INVALID_HANDLE);
|
||||
auto ret =
|
||||
has_open_info(static_cast<native_handle>(
|
||||
reinterpret_cast<remote::file_handle>(file_desc)),
|
||||
STATUS_INVALID_HANDLE);
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
ret =
|
||||
utils::file::is_directory(file_path)
|
||||
@ -994,10 +1004,11 @@ auto remote_server::winfsp_cleanup(PVOID /*file_desc*/, PWSTR file_name,
|
||||
auto remote_server::winfsp_close(PVOID file_desc) -> packet::error_type {
|
||||
std::string file_path;
|
||||
const auto handle = reinterpret_cast<remote::file_handle>(file_desc);
|
||||
if (has_open_info(handle, STATUS_INVALID_HANDLE) == STATUS_SUCCESS) {
|
||||
file_path = get_open_file_path(handle);
|
||||
close(handle);
|
||||
remove_open_info(handle);
|
||||
if (has_open_info(static_cast<native_handle>(handle),
|
||||
STATUS_INVALID_HANDLE) == STATUS_SUCCESS) {
|
||||
file_path = get_open_file_path(static_cast<native_handle>(handle));
|
||||
close(static_cast<native_handle>(handle));
|
||||
remove_open_info(static_cast<native_handle>(handle));
|
||||
}
|
||||
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(__FUNCTION__, file_path, STATUS_SUCCESS);
|
||||
@ -1006,7 +1017,7 @@ auto remote_server::winfsp_close(PVOID file_desc) -> packet::error_type {
|
||||
|
||||
auto remote_server::winfsp_create(PWSTR file_name, UINT32 create_options,
|
||||
UINT32 granted_access, UINT32 attributes,
|
||||
UINT64 /*allocationSize*/, PVOID *file_desc,
|
||||
UINT64 /*allocation_size*/, PVOID *file_desc,
|
||||
remote::file_info *file_info,
|
||||
std::string &normalized_name, BOOLEAN &exists)
|
||||
-> packet::error_type {
|
||||
@ -1056,15 +1067,19 @@ auto remote_server::winfsp_create(PWSTR file_name, UINT32 create_options,
|
||||
auto remote_server::winfsp_flush(PVOID file_desc, remote::file_info *file_info)
|
||||
-> packet::error_type {
|
||||
const auto handle = reinterpret_cast<remote::file_handle>(file_desc);
|
||||
auto ret = has_open_info(handle, STATUS_INVALID_HANDLE);
|
||||
auto ret =
|
||||
has_open_info(static_cast<native_handle>(handle), STATUS_INVALID_HANDLE);
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
ret = (fsync(static_cast<int>(handle)) < 0)
|
||||
ret = (fsync(static_cast<native_handle>(handle)) < 0)
|
||||
? utils::unix_error_to_windows(errno)
|
||||
: populate_file_info(
|
||||
construct_api_path(get_open_file_path(handle)), *file_info);
|
||||
: populate_file_info(construct_api_path(get_open_file_path(
|
||||
static_cast<native_handle>(handle))),
|
||||
*file_info);
|
||||
}
|
||||
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(__FUNCTION__, get_open_file_path(handle), ret);
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(
|
||||
__FUNCTION__, get_open_file_path(static_cast<native_handle>(handle)),
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1072,20 +1087,24 @@ auto remote_server::winfsp_get_file_info(PVOID file_desc,
|
||||
remote::file_info *file_info)
|
||||
-> packet::error_type {
|
||||
const auto handle = reinterpret_cast<remote::file_handle>(file_desc);
|
||||
auto ret = has_open_info(handle, STATUS_INVALID_HANDLE);
|
||||
auto ret =
|
||||
has_open_info(static_cast<native_handle>(handle), STATUS_INVALID_HANDLE);
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
ret = populate_file_info(construct_api_path(get_open_file_path(handle)),
|
||||
ret = populate_file_info(construct_api_path(get_open_file_path(
|
||||
static_cast<native_handle>(handle))),
|
||||
*file_info);
|
||||
}
|
||||
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(__FUNCTION__, get_open_file_path(handle), ret);
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(
|
||||
__FUNCTION__, get_open_file_path(static_cast<native_handle>(handle)),
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto remote_server::winfsp_get_security_by_name(
|
||||
PWSTR file_name, PUINT32 attributes,
|
||||
std::uint64_t * /*securityDescriptorSize*/,
|
||||
std::wstring & /*strDescriptor*/) -> packet::error_type {
|
||||
std::uint64_t * /*security_descriptor_size*/,
|
||||
std::wstring & /*str_descriptor*/) -> packet::error_type {
|
||||
auto ret = STATUS_SUCCESS;
|
||||
const auto file_path = construct_path(file_name);
|
||||
if (utils::file::is_file(file_path) ||
|
||||
@ -1159,14 +1178,16 @@ auto remote_server::winfsp_open(PWSTR file_name, UINT32 create_options,
|
||||
|
||||
auto remote_server::winfsp_overwrite(PVOID file_desc, UINT32 attributes,
|
||||
BOOLEAN replace_attributes,
|
||||
UINT64 /*allocationSize*/,
|
||||
UINT64 /*allocation_size*/,
|
||||
remote::file_info *file_info)
|
||||
-> packet::error_type {
|
||||
const auto handle = reinterpret_cast<remote::file_handle>(file_desc);
|
||||
auto ret = has_open_info(handle, STATUS_INVALID_HANDLE);
|
||||
auto ret =
|
||||
has_open_info(static_cast<native_handle>(handle), STATUS_INVALID_HANDLE);
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
const auto api_path = construct_api_path(get_open_file_path(handle));
|
||||
const auto res = ftruncate(handle, 0);
|
||||
const auto api_path = construct_api_path(
|
||||
get_open_file_path(static_cast<native_handle>(handle)));
|
||||
const auto res = ftruncate(static_cast<native_handle>(handle), 0);
|
||||
if (res >= 0) {
|
||||
auto set_attributes = false;
|
||||
if (replace_attributes) {
|
||||
@ -1195,14 +1216,17 @@ auto remote_server::winfsp_overwrite(PVOID file_desc, UINT32 attributes,
|
||||
drive_.set_item_meta(api_path, META_ATTRIBUTES,
|
||||
std::to_string(attributes));
|
||||
}
|
||||
ret = populate_file_info(construct_api_path(get_open_file_path(handle)),
|
||||
ret = populate_file_info(construct_api_path(get_open_file_path(
|
||||
static_cast<native_handle>(handle))),
|
||||
*file_info);
|
||||
} else {
|
||||
ret = utils::unix_error_to_windows(errno);
|
||||
}
|
||||
}
|
||||
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(__FUNCTION__, get_open_file_path(handle), ret);
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(
|
||||
__FUNCTION__, get_open_file_path(static_cast<native_handle>(handle)),
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1212,17 +1236,21 @@ auto remote_server::winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||
*bytes_transferred = 0;
|
||||
|
||||
const auto handle = reinterpret_cast<remote::file_handle>(file_desc);
|
||||
auto ret = has_open_info(handle, STATUS_INVALID_HANDLE);
|
||||
auto ret =
|
||||
has_open_info(static_cast<native_handle>(handle), STATUS_INVALID_HANDLE);
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
const auto res = pread64(handle, buffer, length, offset);
|
||||
const auto res = pread64(static_cast<native_handle>(handle), buffer, length,
|
||||
static_cast<off_t>(offset));
|
||||
if (res >= 0) {
|
||||
*bytes_transferred = res;
|
||||
*bytes_transferred = static_cast<UINT32>(res);
|
||||
} else {
|
||||
ret = utils::unix_error_to_windows(errno);
|
||||
}
|
||||
}
|
||||
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(__FUNCTION__, get_open_file_path(handle), ret);
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(
|
||||
__FUNCTION__, get_open_file_path(static_cast<native_handle>(handle)),
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1232,9 +1260,11 @@ auto remote_server::winfsp_read_directory(PVOID file_desc, PWSTR /*pattern*/,
|
||||
item_list.clear();
|
||||
|
||||
const auto handle = reinterpret_cast<remote::file_handle>(file_desc);
|
||||
auto ret = has_open_info(handle, STATUS_INVALID_HANDLE);
|
||||
auto ret =
|
||||
has_open_info(static_cast<native_handle>(handle), STATUS_INVALID_HANDLE);
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
const auto api_path = construct_api_path(get_open_file_path(handle));
|
||||
const auto api_path = construct_api_path(
|
||||
get_open_file_path(static_cast<native_handle>(handle)));
|
||||
auto list = drive_.get_directory_items(api_path);
|
||||
directory_iterator iterator(std::move(list));
|
||||
auto offset = marker
|
||||
@ -1253,7 +1283,9 @@ auto remote_server::winfsp_read_directory(PVOID file_desc, PWSTR /*pattern*/,
|
||||
ret = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(__FUNCTION__, get_open_file_path(handle), ret);
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(
|
||||
__FUNCTION__, get_open_file_path(static_cast<native_handle>(handle)),
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1288,9 +1320,11 @@ auto remote_server::winfsp_set_basic_info(
|
||||
UINT64 last_access_time, UINT64 last_write_time, UINT64 change_time,
|
||||
remote::file_info *file_info) -> packet::error_type {
|
||||
const auto handle = reinterpret_cast<remote::file_handle>(file_desc);
|
||||
auto ret = has_open_info(handle, STATUS_INVALID_HANDLE);
|
||||
auto ret =
|
||||
has_open_info(static_cast<native_handle>(handle), STATUS_INVALID_HANDLE);
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
const auto file_path = get_open_file_path(handle);
|
||||
const auto file_path =
|
||||
get_open_file_path(static_cast<native_handle>(handle));
|
||||
if (attributes == INVALID_FILE_ATTRIBUTES) {
|
||||
attributes = 0;
|
||||
} else if (attributes == 0) {
|
||||
@ -1337,7 +1371,9 @@ auto remote_server::winfsp_set_basic_info(
|
||||
ret = populate_file_info(api_path, *file_info);
|
||||
}
|
||||
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(__FUNCTION__, get_open_file_path(handle), ret);
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(
|
||||
__FUNCTION__, get_open_file_path(static_cast<native_handle>(handle)),
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1346,17 +1382,24 @@ auto remote_server::winfsp_set_file_size(PVOID file_desc, UINT64 new_size,
|
||||
remote::file_info *file_info)
|
||||
-> packet::error_type {
|
||||
const auto handle = reinterpret_cast<remote::file_handle>(file_desc);
|
||||
auto ret = has_open_info(handle, STATUS_INVALID_HANDLE);
|
||||
auto ret =
|
||||
has_open_info(static_cast<native_handle>(handle), STATUS_INVALID_HANDLE);
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
const auto res = set_allocation_size ? 0 : ftruncate(handle, new_size);
|
||||
const auto res =
|
||||
set_allocation_size
|
||||
? 0
|
||||
: ftruncate(static_cast<native_handle>(handle), new_size);
|
||||
ret = ((res < 0) ? utils::unix_error_to_windows(errno) : 0);
|
||||
if (ret == 0) {
|
||||
ret = populate_file_info(construct_api_path(get_open_file_path(handle)),
|
||||
ret = populate_file_info(construct_api_path(get_open_file_path(
|
||||
static_cast<native_handle>(handle))),
|
||||
*file_info);
|
||||
}
|
||||
}
|
||||
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(__FUNCTION__, get_open_file_path(handle), ret);
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(
|
||||
__FUNCTION__, get_open_file_path(static_cast<native_handle>(handle)),
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1375,9 +1418,11 @@ auto remote_server::winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||
-> packet::error_type {
|
||||
*bytes_transferred = 0;
|
||||
const auto handle = reinterpret_cast<remote::file_handle>(file_desc);
|
||||
auto ret = has_open_info(handle, STATUS_INVALID_HANDLE);
|
||||
auto ret =
|
||||
has_open_info(static_cast<native_handle>(handle), STATUS_INVALID_HANDLE);
|
||||
if (ret == STATUS_SUCCESS) {
|
||||
const auto api_path = construct_api_path(get_open_file_path(handle));
|
||||
const auto api_path = construct_api_path(
|
||||
get_open_file_path(static_cast<native_handle>(handle)));
|
||||
const auto file_size = drive_.get_file_size(api_path);
|
||||
if (write_to_end) {
|
||||
offset = file_size;
|
||||
@ -1389,17 +1434,19 @@ auto remote_server::winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||
ret = STATUS_SUCCESS;
|
||||
should_write = false;
|
||||
} else if ((offset + length) > file_size) {
|
||||
length = static_cast<UINT64>(file_size - offset);
|
||||
length = static_cast<UINT32>(file_size - offset);
|
||||
}
|
||||
}
|
||||
|
||||
if (should_write) {
|
||||
if (length > 0) {
|
||||
const auto res = pwrite64(handle, buffer, length, offset);
|
||||
const auto res = pwrite64(static_cast<native_handle>(handle), buffer,
|
||||
length, static_cast<off_t>(offset));
|
||||
if (res >= 0) {
|
||||
*bytes_transferred = res;
|
||||
ret = populate_file_info(
|
||||
construct_api_path(get_open_file_path(handle)), *file_info);
|
||||
*bytes_transferred = static_cast<UINT32>(res);
|
||||
ret = populate_file_info(construct_api_path(get_open_file_path(
|
||||
static_cast<native_handle>(handle))),
|
||||
*file_info);
|
||||
} else {
|
||||
ret = utils::unix_error_to_windows(errno);
|
||||
}
|
||||
@ -1407,7 +1454,9 @@ auto remote_server::winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||
}
|
||||
}
|
||||
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(__FUNCTION__, get_open_file_path(handle), ret);
|
||||
RAISE_REMOTE_FUSE_SERVER_EVENT(
|
||||
__FUNCTION__, get_open_file_path(static_cast<native_handle>(handle)),
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1444,8 +1493,8 @@ auto remote_server::json_read_directory_snapshot(
|
||||
std::uint32_t page, json &json_data) -> packet::error_type {
|
||||
const auto file_path = construct_path(path);
|
||||
auto *iterator = reinterpret_cast<directory_iterator *>(handle);
|
||||
std::size_t offset = 0u;
|
||||
int res;
|
||||
std::size_t offset{};
|
||||
int res{};
|
||||
json item_json;
|
||||
while ((json_data["directory_list"].size() < REPERTORY_DIRECTORY_PAGE_SIZE) &&
|
||||
(res = iterator->get_json(
|
||||
|
@ -260,8 +260,8 @@ VOID winfsp_drive::Close(PVOID /*file_node*/, PVOID file_desc) {
|
||||
RAISE_WINFSP_EVENT(__FUNCTION__, api_path, 0);
|
||||
}
|
||||
|
||||
auto winfsp_drive::Create(PWSTR fileName, UINT32 create_options,
|
||||
UINT32 /*grantedAccess*/, UINT32 attributes,
|
||||
auto winfsp_drive::Create(PWSTR file_name, UINT32 create_options,
|
||||
UINT32 /*granted_access*/, UINT32 attributes,
|
||||
PSECURITY_DESCRIPTOR /*descriptor*/,
|
||||
UINT64 /*allocation_size*/, PVOID * /*file_node*/,
|
||||
PVOID *file_desc, OpenFileInfo *ofi) -> NTSTATUS {
|
||||
@ -281,8 +281,8 @@ auto winfsp_drive::Create(PWSTR fileName, UINT32 create_options,
|
||||
|
||||
const auto now = utils::get_file_time_now();
|
||||
auto meta = create_meta_attributes(
|
||||
now, attributes, now, now, attributes & FILE_ATTRIBUTE_DIRECTORY, "", 0U,
|
||||
"", 0U, now, 0U, 0U, 0U,
|
||||
now, attributes, now, now, attributes & FILE_ATTRIBUTE_DIRECTORY, 0U, "",
|
||||
0U, now, 0U, 0U, 0U,
|
||||
(attributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
? ""
|
||||
: utils::path::combine(config_.get_cache_directory(),
|
||||
@ -290,7 +290,7 @@ auto winfsp_drive::Create(PWSTR fileName, UINT32 create_options,
|
||||
0U, now);
|
||||
|
||||
const auto api_path =
|
||||
utils::path::create_api_path(utils::string::to_utf8(fileName));
|
||||
utils::path::create_api_path(utils::string::to_utf8(file_name));
|
||||
|
||||
open_file_data ofd{};
|
||||
std::uint64_t handle{};
|
||||
@ -315,7 +315,7 @@ auto winfsp_drive::Create(PWSTR fileName, UINT32 create_options,
|
||||
}
|
||||
|
||||
auto winfsp_drive::Flush(PVOID /*file_node*/, PVOID file_desc,
|
||||
FileInfo *fileInfo) -> NTSTATUS {
|
||||
FileInfo *file_info) -> NTSTATUS {
|
||||
std::string api_path;
|
||||
auto error = api_error::success;
|
||||
auto handle =
|
||||
@ -336,7 +336,7 @@ auto winfsp_drive::Flush(PVOID /*file_node*/, PVOID file_desc,
|
||||
// Populate file information
|
||||
api_meta_map meta;
|
||||
if (provider_.get_item_meta(api_path, meta) == api_error::success) {
|
||||
populate_file_info(f->get_file_size(), meta, *fileInfo);
|
||||
populate_file_info(f->get_file_size(), meta, *file_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -363,7 +363,7 @@ auto winfsp_drive::get_directory_items(const std::string &api_path) const
|
||||
}
|
||||
|
||||
auto winfsp_drive::GetFileInfo(PVOID /*file_node*/, PVOID file_desc,
|
||||
FileInfo *fileInfo) -> NTSTATUS {
|
||||
FileInfo *file_info) -> NTSTATUS {
|
||||
std::string api_path;
|
||||
auto error = api_error::invalid_handle;
|
||||
auto handle =
|
||||
@ -375,7 +375,7 @@ auto winfsp_drive::GetFileInfo(PVOID /*file_node*/, PVOID file_desc,
|
||||
api_meta_map meta;
|
||||
if ((error = provider_.get_item_meta(api_path, meta)) ==
|
||||
api_error::success) {
|
||||
populate_file_info(f->get_file_size(), meta, *fileInfo);
|
||||
populate_file_info(f->get_file_size(), meta, *file_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -414,12 +414,12 @@ auto winfsp_drive::get_item_meta(const std::string &api_path,
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto winfsp_drive::get_security_by_name(PWSTR fileName, PUINT32 attributes,
|
||||
auto winfsp_drive::get_security_by_name(PWSTR file_name, PUINT32 attributes,
|
||||
PSECURITY_DESCRIPTOR descriptor,
|
||||
std::uint64_t *descriptor_size)
|
||||
-> NTSTATUS {
|
||||
const auto api_path =
|
||||
utils::path::create_api_path(utils::string::to_utf8(fileName));
|
||||
utils::path::create_api_path(utils::string::to_utf8(file_name));
|
||||
|
||||
api_meta_map meta{};
|
||||
auto error = provider_.get_item_meta(api_path, meta);
|
||||
@ -451,13 +451,13 @@ auto winfsp_drive::get_security_by_name(PWSTR fileName, PUINT32 attributes,
|
||||
return utils::from_api_error(error);
|
||||
}
|
||||
|
||||
auto winfsp_drive::GetSecurityByName(PWSTR fileName, PUINT32 attributes,
|
||||
auto winfsp_drive::GetSecurityByName(PWSTR file_name, PUINT32 attributes,
|
||||
PSECURITY_DESCRIPTOR descriptor,
|
||||
SIZE_T *descriptor_size) -> NTSTATUS {
|
||||
const auto api_path =
|
||||
utils::path::create_api_path(utils::string::to_utf8(fileName));
|
||||
utils::path::create_api_path(utils::string::to_utf8(file_name));
|
||||
std::uint64_t sds = descriptor_size ? *descriptor_size : 0U;
|
||||
auto ret = get_security_by_name(fileName, attributes, descriptor,
|
||||
auto ret = get_security_by_name(file_name, attributes, descriptor,
|
||||
sds > 0U ? &sds : nullptr);
|
||||
if (sds) {
|
||||
*descriptor_size = static_cast<SIZE_T>(sds);
|
||||
@ -939,7 +939,7 @@ auto winfsp_drive::Rename(PVOID /*file_node*/, PVOID /*file_desc*/,
|
||||
auto winfsp_drive::SetBasicInfo(PVOID /*file_node*/, PVOID file_desc,
|
||||
UINT32 attributes, UINT64 creation_time,
|
||||
UINT64 last_access_time, UINT64 last_write_time,
|
||||
UINT64 change_time, FileInfo *fileInfo)
|
||||
UINT64 change_time, FileInfo *file_info)
|
||||
-> NTSTATUS {
|
||||
std::string api_path;
|
||||
auto error = api_error::invalid_handle;
|
||||
@ -983,7 +983,7 @@ auto winfsp_drive::SetBasicInfo(PVOID /*file_node*/, PVOID file_desc,
|
||||
// Populate file information
|
||||
if (provider_.get_item_meta(api_path, meta) == api_error::success) {
|
||||
populate_file_info(utils::string::to_uint64(meta[META_SIZE]), meta,
|
||||
*fileInfo);
|
||||
*file_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,29 +35,30 @@ namespace repertory {
|
||||
file_manager::open_file::open_file(std::uint64_t chunk_size,
|
||||
std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi, i_provider &provider,
|
||||
i_upload_manager &um)
|
||||
i_upload_manager &mgr)
|
||||
: open_file(chunk_size, chunk_timeout, fsi, {}, provider, std::nullopt,
|
||||
um) {}
|
||||
mgr) {}
|
||||
|
||||
file_manager::open_file::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 &um)
|
||||
i_upload_manager &mgr)
|
||||
: open_file(chunk_size, chunk_timeout, fsi, open_data, provider,
|
||||
std::nullopt, um) {}
|
||||
std::nullopt, mgr) {}
|
||||
|
||||
file_manager::open_file::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 &um)
|
||||
: open_file(chunk_size, chunk_timeout, fsi, {}, provider, read_state, um) {}
|
||||
i_upload_manager &mgr)
|
||||
: open_file(chunk_size, chunk_timeout, fsi, {}, provider, read_state, mgr) {
|
||||
}
|
||||
|
||||
file_manager::open_file::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 &um)
|
||||
std::optional<boost::dynamic_bitset<>> read_state, i_upload_manager &mgr)
|
||||
: open_file_base(chunk_size, chunk_timeout, fsi, open_data, provider),
|
||||
um_(um) {
|
||||
mgr_(mgr) {
|
||||
if (fsi_.directory && read_state.has_value()) {
|
||||
throw startup_exception("cannot resume a directory|" + fsi.api_path);
|
||||
}
|
||||
@ -68,9 +69,9 @@ file_manager::open_file::open_file(
|
||||
if (get_api_error() == api_error::success) {
|
||||
if (read_state.has_value()) {
|
||||
modified_ = true;
|
||||
um_.store_resume(*this);
|
||||
mgr_.store_resume(*this);
|
||||
read_state_ = read_state.value();
|
||||
} else if (fsi_.size > 0u) {
|
||||
} else if (fsi_.size > 0U) {
|
||||
read_state_.resize(static_cast<std::size_t>(utils::divide_with_ceiling(
|
||||
fsi_.size, chunk_size)),
|
||||
false);
|
||||
@ -78,7 +79,7 @@ file_manager::open_file::open_file(
|
||||
std::uint64_t file_size{};
|
||||
if (nf_->get_file_size(file_size)) {
|
||||
if (provider_.is_direct_only() || file_size == fsi.size) {
|
||||
read_state_.set(0u, read_state_.size(), true);
|
||||
read_state_.set(0U, read_state_.size(), true);
|
||||
} else if (not nf_->truncate(fsi.size)) {
|
||||
set_api_error(api_error::os_error);
|
||||
}
|
||||
@ -103,13 +104,13 @@ void file_manager::open_file::download_chunk(std::size_t chunk,
|
||||
reset_timeout();
|
||||
}
|
||||
|
||||
unique_recur_mutex_lock file_lock(file_mtx_);
|
||||
unique_recur_mutex_lock download_lock(file_mtx_);
|
||||
if ((get_api_error() == api_error::success) && (chunk < read_state_.size()) &&
|
||||
not read_state_[chunk]) {
|
||||
if (active_downloads_.find(chunk) != active_downloads_.end()) {
|
||||
if (not skip_active) {
|
||||
auto active_download = active_downloads_.at(chunk);
|
||||
file_lock.unlock();
|
||||
download_lock.unlock();
|
||||
|
||||
active_download->wait();
|
||||
}
|
||||
@ -119,8 +120,8 @@ void file_manager::open_file::download_chunk(std::size_t chunk,
|
||||
|
||||
const auto data_offset = chunk * chunk_size_;
|
||||
const auto data_size =
|
||||
(chunk == read_state_.size() - 1u) ? last_chunk_size_ : chunk_size_;
|
||||
if (active_downloads_.empty() && (read_state_.count() == 0u)) {
|
||||
(chunk == read_state_.size() - 1U) ? last_chunk_size_ : chunk_size_;
|
||||
if (active_downloads_.empty() && (read_state_.count() == 0U)) {
|
||||
event_system::instance().raise<download_begin>(fsi_.api_path,
|
||||
fsi_.source_path);
|
||||
}
|
||||
@ -129,7 +130,7 @@ void file_manager::open_file::download_chunk(std::size_t chunk,
|
||||
read_state_.count());
|
||||
|
||||
active_downloads_[chunk] = std::make_shared<download>();
|
||||
file_lock.unlock();
|
||||
download_lock.unlock();
|
||||
|
||||
if (should_reset) {
|
||||
reset_timeout();
|
||||
@ -237,19 +238,19 @@ auto file_manager::open_file::is_complete() const -> bool {
|
||||
}
|
||||
|
||||
auto file_manager::open_file::native_operation(
|
||||
const i_open_file::native_operation_callback &operation) -> api_error {
|
||||
const i_open_file::native_operation_callback &callback) -> api_error {
|
||||
unique_recur_mutex_lock file_lock(file_mtx_);
|
||||
if (stop_requested_) {
|
||||
return api_error::download_stopped;
|
||||
}
|
||||
file_lock.unlock();
|
||||
|
||||
return do_io([&]() -> api_error { return operation(nf_->get_handle()); });
|
||||
return do_io([&]() -> api_error { return callback(nf_->get_handle()); });
|
||||
}
|
||||
|
||||
auto file_manager::open_file::native_operation(
|
||||
std::uint64_t new_file_size,
|
||||
const i_open_file::native_operation_callback &operation) -> api_error {
|
||||
const i_open_file::native_operation_callback &callback) -> api_error {
|
||||
if (fsi_.directory) {
|
||||
return api_error::invalid_operation;
|
||||
}
|
||||
@ -260,17 +261,17 @@ auto file_manager::open_file::native_operation(
|
||||
}
|
||||
file_lock.unlock();
|
||||
|
||||
const auto is_empty_file = new_file_size == 0u;
|
||||
const auto is_empty_file = new_file_size == 0U;
|
||||
const auto last_chunk =
|
||||
is_empty_file ? std::size_t(0u)
|
||||
is_empty_file ? std::size_t(0U)
|
||||
: static_cast<std::size_t>(utils::divide_with_ceiling(
|
||||
new_file_size, chunk_size_)) -
|
||||
1u;
|
||||
1U;
|
||||
|
||||
file_lock.lock();
|
||||
if (not is_empty_file && (last_chunk < read_state_.size())) {
|
||||
file_lock.unlock();
|
||||
update_background_reader(0u);
|
||||
update_background_reader(0U);
|
||||
|
||||
download_chunk(last_chunk, false, true);
|
||||
if (get_api_error() != api_error::success) {
|
||||
@ -281,7 +282,7 @@ auto file_manager::open_file::native_operation(
|
||||
|
||||
const auto original_file_size = get_file_size();
|
||||
|
||||
auto res = do_io([&]() -> api_error { return operation(nf_->get_handle()); });
|
||||
auto res = do_io([&]() -> api_error { return callback(nf_->get_handle()); });
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, get_api_path(),
|
||||
utils::get_last_error_code(),
|
||||
@ -308,25 +309,25 @@ auto file_manager::open_file::native_operation(
|
||||
}
|
||||
}
|
||||
|
||||
if (is_empty_file || (read_state_.size() != (last_chunk + 1u))) {
|
||||
read_state_.resize(is_empty_file ? 0u : last_chunk + 1u);
|
||||
if (is_empty_file || (read_state_.size() != (last_chunk + 1U))) {
|
||||
read_state_.resize(is_empty_file ? 0U : last_chunk + 1U);
|
||||
|
||||
if (not is_empty_file) {
|
||||
read_state_[last_chunk] = true;
|
||||
}
|
||||
|
||||
last_chunk_size_ = static_cast<std::size_t>(
|
||||
new_file_size <= chunk_size_ ? new_file_size
|
||||
: new_file_size % chunk_size_ ? new_file_size % chunk_size_
|
||||
: chunk_size_);
|
||||
new_file_size <= chunk_size_ ? new_file_size
|
||||
: (new_file_size % chunk_size_) == 0U ? chunk_size_
|
||||
: new_file_size % chunk_size_);
|
||||
}
|
||||
|
||||
if (original_file_size != new_file_size) {
|
||||
if (not modified_) {
|
||||
um_.store_resume(*this);
|
||||
mgr_.store_resume(*this);
|
||||
}
|
||||
modified_ = true;
|
||||
um_.remove_upload(get_api_path());
|
||||
mgr_.remove_upload(get_api_path());
|
||||
|
||||
fsi_.size = new_file_size;
|
||||
const auto now = std::to_string(utils::get_file_time_now());
|
||||
@ -356,7 +357,7 @@ auto file_manager::open_file::read(std::size_t read_size,
|
||||
|
||||
read_size =
|
||||
utils::calculate_read_size(get_file_size(), read_size, read_offset);
|
||||
if (read_size == 0u) {
|
||||
if (read_size == 0U) {
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
@ -405,7 +406,7 @@ void file_manager::open_file::remove(std::uint64_t handle) {
|
||||
open_file_base::remove(handle);
|
||||
if (modified_ && read_state_.all() &&
|
||||
(get_api_error() == api_error::success)) {
|
||||
um_.queue_upload(*this);
|
||||
mgr_.queue_upload(*this);
|
||||
modified_ = false;
|
||||
}
|
||||
}
|
||||
@ -443,7 +444,7 @@ auto file_manager::open_file::close() -> bool {
|
||||
err == api_error::download_stopped) {
|
||||
if (modified_ && not read_state_.all()) {
|
||||
set_api_error(api_error::download_incomplete);
|
||||
} else if (not modified_ && (fsi_.size > 0u) &&
|
||||
} else if (not modified_ && (fsi_.size > 0U) &&
|
||||
not read_state_.all()) {
|
||||
set_api_error(api_error::download_stopped);
|
||||
}
|
||||
@ -454,12 +455,12 @@ auto file_manager::open_file::close() -> bool {
|
||||
nf_.reset();
|
||||
|
||||
if (modified_ && (get_api_error() == api_error::success)) {
|
||||
um_.queue_upload(*this);
|
||||
mgr_.queue_upload(*this);
|
||||
} else if (modified_ &&
|
||||
(get_api_error() == api_error::download_incomplete)) {
|
||||
um_.store_resume(*this);
|
||||
mgr_.store_resume(*this);
|
||||
} else if (get_api_error() != api_error::success) {
|
||||
um_.remove_resume(get_api_path(), get_source_path());
|
||||
mgr_.remove_resume(get_api_path(), get_source_path());
|
||||
if (not utils::file::retry_delete_file(fsi_.source_path)) {
|
||||
utils::error::raise_api_path_error(
|
||||
__FUNCTION__, get_api_path(), fsi_.source_path,
|
||||
@ -486,15 +487,15 @@ auto file_manager::open_file::close() -> bool {
|
||||
}
|
||||
|
||||
void file_manager::open_file::update_background_reader(std::size_t read_chunk) {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
recur_mutex_lock reader_lock(file_mtx_);
|
||||
read_chunk_index_ = read_chunk;
|
||||
|
||||
if (not reader_thread_ && not stop_requested_) {
|
||||
reader_thread_ = std::make_unique<std::thread>([this]() {
|
||||
auto next_chunk = 0u;
|
||||
std::size_t next_chunk{};
|
||||
while (not stop_requested_) {
|
||||
unique_recur_mutex_lock file_lock(file_mtx_);
|
||||
if ((fsi_.size == 0u) || read_state_.all()) {
|
||||
if ((fsi_.size == 0U) || read_state_.all()) {
|
||||
file_lock.unlock();
|
||||
|
||||
unique_mutex_lock io_lock(io_thread_mtx_);
|
||||
@ -506,10 +507,10 @@ void file_manager::open_file::update_background_reader(std::size_t read_chunk) {
|
||||
} else {
|
||||
do {
|
||||
next_chunk = read_chunk_index_ =
|
||||
((read_chunk_index_ + 1u) >= read_state_.size())
|
||||
? 0u
|
||||
: read_chunk_index_ + 1u;
|
||||
} while ((next_chunk != 0u) && (active_downloads_.find(next_chunk) !=
|
||||
((read_chunk_index_ + 1U) >= read_state_.size())
|
||||
? 0U
|
||||
: read_chunk_index_ + 1U;
|
||||
} while ((next_chunk != 0U) && (active_downloads_.find(next_chunk) !=
|
||||
active_downloads_.end()));
|
||||
|
||||
file_lock.unlock();
|
||||
@ -523,7 +524,7 @@ void file_manager::open_file::update_background_reader(std::size_t read_chunk) {
|
||||
auto file_manager::open_file::write(std::uint64_t write_offset,
|
||||
const data_buffer &data,
|
||||
std::size_t &bytes_written) -> api_error {
|
||||
bytes_written = 0u;
|
||||
bytes_written = 0U;
|
||||
|
||||
if (fsi_.directory || provider_.is_direct_only()) {
|
||||
return api_error::invalid_operation;
|
||||
@ -533,11 +534,11 @@ auto file_manager::open_file::write(std::uint64_t write_offset,
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
unique_recur_mutex_lock file_lock(file_mtx_);
|
||||
unique_recur_mutex_lock write_lock(file_mtx_);
|
||||
if (stop_requested_) {
|
||||
return api_error::download_stopped;
|
||||
}
|
||||
file_lock.unlock();
|
||||
write_lock.unlock();
|
||||
|
||||
const auto start_chunk_index =
|
||||
static_cast<std::size_t>(write_offset / chunk_size_);
|
||||
@ -547,12 +548,12 @@ auto file_manager::open_file::write(std::uint64_t write_offset,
|
||||
update_background_reader(start_chunk_index);
|
||||
|
||||
download_range(start_chunk_index,
|
||||
std::min(read_state_.size() - 1u, end_chunk_index), true);
|
||||
std::min(read_state_.size() - 1U, end_chunk_index), true);
|
||||
if (get_api_error() != api_error::success) {
|
||||
return get_api_error();
|
||||
}
|
||||
|
||||
file_lock.lock();
|
||||
write_lock.lock();
|
||||
if ((write_offset + data.size()) > fsi_.size) {
|
||||
auto res = resize(write_offset + data.size());
|
||||
if (res != api_error::success) {
|
||||
@ -586,10 +587,10 @@ auto file_manager::open_file::write(std::uint64_t write_offset,
|
||||
}
|
||||
|
||||
if (not modified_) {
|
||||
um_.store_resume(*this);
|
||||
mgr_.store_resume(*this);
|
||||
}
|
||||
modified_ = true;
|
||||
um_.remove_upload(get_api_path());
|
||||
mgr_.remove_upload(get_api_path());
|
||||
|
||||
return api_error::success;
|
||||
}
|
||||
|
@ -37,9 +37,9 @@ file_manager::open_file_base::open_file_base(
|
||||
chunk_timeout_(chunk_timeout),
|
||||
fsi_(std::move(fsi)),
|
||||
last_chunk_size_(static_cast<std::size_t>(
|
||||
fsi.size <= chunk_size ? fsi.size
|
||||
: fsi.size % chunk_size ? fsi.size % chunk_size
|
||||
: chunk_size)),
|
||||
fsi.size <= chunk_size ? fsi.size
|
||||
: (fsi.size % chunk_size) == 0U ? chunk_size
|
||||
: fsi.size % chunk_size)),
|
||||
open_data_(std::move(open_data)),
|
||||
provider_(provider) {
|
||||
if (not fsi.directory) {
|
||||
@ -51,7 +51,7 @@ void file_manager::open_file_base::add(std::uint64_t handle,
|
||||
open_file_data ofd) {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
open_data_[handle] = ofd;
|
||||
if (open_data_.size() == 1u) {
|
||||
if (open_data_.size() == 1U) {
|
||||
event_system::instance().raise<filesystem_item_opened>(
|
||||
fsi_.api_path, fsi_.source_path, fsi_.directory);
|
||||
}
|
||||
@ -157,8 +157,8 @@ auto file_manager::open_file_base::get_handles() const
|
||||
-> std::vector<std::uint64_t> {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
std::vector<std::uint64_t> ret;
|
||||
for (const auto &kv : open_data_) {
|
||||
ret.emplace_back(kv.first);
|
||||
for (const auto &item : open_data_) {
|
||||
ret.emplace_back(item.first);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -201,14 +201,14 @@ void file_manager::open_file_base::reset_timeout() {
|
||||
last_access_ = std::chrono::system_clock::now();
|
||||
}
|
||||
|
||||
auto file_manager::open_file_base::set_api_error(const api_error &e)
|
||||
auto file_manager::open_file_base::set_api_error(const api_error &err)
|
||||
-> api_error {
|
||||
mutex_lock error_lock(error_mtx_);
|
||||
if (error_ != e) {
|
||||
if (error_ != err) {
|
||||
return ((error_ = (error_ == api_error::success ||
|
||||
error_ == api_error::download_incomplete ||
|
||||
error_ == api_error::download_stopped
|
||||
? e
|
||||
? err
|
||||
: error_)));
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ file_manager::ring_buffer_open_file::ring_buffer_open_file(
|
||||
std::uint8_t chunk_timeout, filesystem_item fsi, i_provider &provider)
|
||||
: ring_buffer_open_file(std::move(buffer_directory), chunk_size,
|
||||
chunk_timeout, std::move(fsi), provider,
|
||||
(1024ull * 1024ull * 1024ull) / chunk_size) {}
|
||||
(1024ULL * 1024ULL * 1024ULL) / chunk_size) {}
|
||||
|
||||
file_manager::ring_buffer_open_file::ring_buffer_open_file(
|
||||
std::string buffer_directory, std::uint64_t chunk_size,
|
||||
@ -47,11 +47,11 @@ file_manager::ring_buffer_open_file::ring_buffer_open_file(
|
||||
ring_state_(ring_size),
|
||||
total_chunks_(static_cast<std::size_t>(
|
||||
utils::divide_with_ceiling(fsi.size, chunk_size_))) {
|
||||
if (ring_size % 2u) {
|
||||
if ((ring_size % 2U) != 0U) {
|
||||
throw std::runtime_error("ring size must be a multiple of 2");
|
||||
}
|
||||
|
||||
if (ring_size < 4u) {
|
||||
if (ring_size < 4U) {
|
||||
throw std::runtime_error("ring size must be greater than or equal to 4");
|
||||
}
|
||||
|
||||
@ -59,8 +59,8 @@ file_manager::ring_buffer_open_file::ring_buffer_open_file(
|
||||
throw std::runtime_error("file size is less than ring buffer size");
|
||||
}
|
||||
|
||||
last_chunk_ = ring_state_.size() - 1u;
|
||||
ring_state_.set(0u, ring_state_.size(), true);
|
||||
last_chunk_ = ring_state_.size() - 1U;
|
||||
ring_state_.set(0U, ring_state_.size(), true);
|
||||
|
||||
buffer_directory = utils::path::absolute(buffer_directory);
|
||||
if (not utils::file::create_full_directory_path(buffer_directory)) {
|
||||
@ -113,7 +113,7 @@ auto file_manager::file_manager::ring_buffer_open_file::download_chunk(
|
||||
chunk_notify_.notify_all();
|
||||
chunk_lock.unlock();
|
||||
|
||||
data_buffer buffer((chunk == (total_chunks_ - 1u)) ? last_chunk_size_
|
||||
data_buffer buffer((chunk == (total_chunks_ - 1U)) ? last_chunk_size_
|
||||
: chunk_size_);
|
||||
|
||||
stop_type stop_requested = !!ring_state_[chunk % ring_state_.size()];
|
||||
@ -149,8 +149,8 @@ auto file_manager::file_manager::ring_buffer_open_file::download_chunk(
|
||||
|
||||
void file_manager::ring_buffer_open_file::forward(std::size_t count) {
|
||||
mutex_lock chunk_lock(chunk_mtx_);
|
||||
if ((current_chunk_ + count) > (total_chunks_ - 1u)) {
|
||||
count = (total_chunks_ - 1u) - current_chunk_;
|
||||
if ((current_chunk_ + count) > (total_chunks_ - 1U)) {
|
||||
count = (total_chunks_ - 1U) - current_chunk_;
|
||||
}
|
||||
|
||||
if ((current_chunk_ + count) <= last_chunk_) {
|
||||
@ -158,19 +158,19 @@ void file_manager::ring_buffer_open_file::forward(std::size_t count) {
|
||||
} else {
|
||||
const auto added = count - (last_chunk_ - current_chunk_);
|
||||
if (added >= ring_state_.size()) {
|
||||
ring_state_.set(0u, ring_state_.size(), true);
|
||||
ring_state_.set(0U, ring_state_.size(), true);
|
||||
current_chunk_ += count;
|
||||
first_chunk_ += added;
|
||||
last_chunk_ =
|
||||
std::min(total_chunks_ - 1u, first_chunk_ + ring_state_.size() - 1u);
|
||||
std::min(total_chunks_ - 1U, first_chunk_ + ring_state_.size() - 1U);
|
||||
} else {
|
||||
for (std::size_t i = 0u; i < added; i++) {
|
||||
for (std::size_t i = 0U; i < added; i++) {
|
||||
ring_state_[(first_chunk_ + i) % ring_state_.size()] = true;
|
||||
}
|
||||
first_chunk_ += added;
|
||||
current_chunk_ += count;
|
||||
last_chunk_ =
|
||||
std::min(total_chunks_ - 1u, first_chunk_ + ring_state_.size() - 1u);
|
||||
std::min(total_chunks_ - 1U, first_chunk_ + ring_state_.size() - 1U);
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,8 +195,8 @@ auto file_manager::ring_buffer_open_file::is_download_complete() const -> bool {
|
||||
}
|
||||
|
||||
auto file_manager::ring_buffer_open_file::native_operation(
|
||||
const i_open_file::native_operation_callback &operation) -> api_error {
|
||||
return do_io([&]() -> api_error { return operation(nf_->get_handle()); });
|
||||
const i_open_file::native_operation_callback &callback) -> api_error {
|
||||
return do_io([&]() -> api_error { return callback(nf_->get_handle()); });
|
||||
}
|
||||
|
||||
void file_manager::ring_buffer_open_file::reverse(std::size_t count) {
|
||||
@ -210,19 +210,19 @@ void file_manager::ring_buffer_open_file::reverse(std::size_t count) {
|
||||
} else {
|
||||
const auto removed = count - (current_chunk_ - first_chunk_);
|
||||
if (removed >= ring_state_.size()) {
|
||||
ring_state_.set(0u, ring_state_.size(), true);
|
||||
ring_state_.set(0U, ring_state_.size(), true);
|
||||
current_chunk_ -= count;
|
||||
first_chunk_ = current_chunk_;
|
||||
last_chunk_ =
|
||||
std::min(total_chunks_ - 1u, first_chunk_ + ring_state_.size() - 1u);
|
||||
std::min(total_chunks_ - 1U, first_chunk_ + ring_state_.size() - 1U);
|
||||
} else {
|
||||
for (std::size_t i = 0u; i < removed; i++) {
|
||||
for (std::size_t i = 0U; i < removed; i++) {
|
||||
ring_state_[(last_chunk_ - i) % ring_state_.size()] = true;
|
||||
}
|
||||
first_chunk_ -= removed;
|
||||
current_chunk_ -= count;
|
||||
last_chunk_ =
|
||||
std::min(total_chunks_ - 1u, first_chunk_ + ring_state_.size() - 1u);
|
||||
std::min(total_chunks_ - 1U, first_chunk_ + ring_state_.size() - 1U);
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,7 +239,7 @@ auto file_manager::ring_buffer_open_file::read(std::size_t read_size,
|
||||
reset_timeout();
|
||||
|
||||
read_size = utils::calculate_read_size(fsi_.size, read_size, read_offset);
|
||||
if (read_size == 0u) {
|
||||
if (read_size == 0U) {
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
@ -250,7 +250,7 @@ auto file_manager::ring_buffer_open_file::read(std::size_t read_size,
|
||||
|
||||
auto res = api_error::success;
|
||||
for (std::size_t chunk = start_chunk_index;
|
||||
(res == api_error::success) && (read_size > 0u); chunk++) {
|
||||
(res == api_error::success) && (read_size > 0U); chunk++) {
|
||||
if (chunk > current_chunk_) {
|
||||
forward(chunk - current_chunk_);
|
||||
} else if (chunk < current_chunk_) {
|
||||
@ -264,20 +264,20 @@ auto file_manager::ring_buffer_open_file::read(std::size_t read_size,
|
||||
res = do_io([this, &buffer, &chunk, &data, read_offset,
|
||||
&to_read]() -> api_error {
|
||||
std::size_t bytes_read{};
|
||||
auto res = nf_->read_bytes(buffer.data(), buffer.size(),
|
||||
auto ret = nf_->read_bytes(buffer.data(), buffer.size(),
|
||||
((chunk % ring_state_.size()) * chunk_size_),
|
||||
bytes_read)
|
||||
? api_error::success
|
||||
: api_error::os_error;
|
||||
if (res == api_error::success) {
|
||||
if (ret == api_error::success) {
|
||||
data.insert(data.end(), buffer.begin() + read_offset,
|
||||
buffer.begin() + read_offset + to_read);
|
||||
reset_timeout();
|
||||
}
|
||||
|
||||
return res;
|
||||
return ret;
|
||||
});
|
||||
read_offset = 0u;
|
||||
read_offset = 0U;
|
||||
read_size -= to_read;
|
||||
}
|
||||
}
|
||||
@ -294,7 +294,7 @@ void file_manager::ring_buffer_open_file::set(std::size_t first_chunk,
|
||||
}
|
||||
|
||||
first_chunk_ = first_chunk;
|
||||
last_chunk_ = first_chunk_ + ring_state_.size() - 1u;
|
||||
last_chunk_ = first_chunk_ + ring_state_.size() - 1U;
|
||||
|
||||
if (current_chunk > last_chunk_) {
|
||||
chunk_notify_.notify_all();
|
||||
@ -303,7 +303,7 @@ void file_manager::ring_buffer_open_file::set(std::size_t first_chunk,
|
||||
}
|
||||
|
||||
current_chunk_ = current_chunk;
|
||||
ring_state_.set(0u, ring_state_.size(), false);
|
||||
ring_state_.set(0U, ring_state_.size(), false);
|
||||
|
||||
chunk_notify_.notify_all();
|
||||
}
|
||||
|
@ -48,8 +48,8 @@ void file_manager::upload::cancel() {
|
||||
void file_manager::upload::stop() { stop_requested_ = true; }
|
||||
|
||||
void file_manager::upload::upload_thread() {
|
||||
error_ = provider_.upload_file(fsi_.api_path, fsi_.source_path,
|
||||
fsi_.encryption_token, stop_requested_);
|
||||
error_ =
|
||||
provider_.upload_file(fsi_.api_path, fsi_.source_path, stop_requested_);
|
||||
if (not utils::file::reset_modified_time(fsi_.source_path)) {
|
||||
utils::error::raise_api_path_error(
|
||||
__FUNCTION__, fsi_.api_path, fsi_.source_path,
|
||||
|
@ -185,11 +185,10 @@ auto lock_data::wait_for_lock(int fd, std::uint8_t retry_count) -> int {
|
||||
auto create_meta_attributes(
|
||||
std::uint64_t accessed_date, std::uint32_t attributes,
|
||||
std::uint64_t changed_date, std::uint64_t creation_date, bool directory,
|
||||
const std::string &encryption_token, std::uint32_t gid,
|
||||
const std::string &key, std::uint32_t mode, std::uint64_t modified_date,
|
||||
std::uint32_t osx_backup, std::uint32_t osx_flags, std::uint64_t size,
|
||||
const std::string &source_path, std::uint32_t uid,
|
||||
std::uint64_t written_date) -> api_meta_map {
|
||||
std::uint32_t gid, const std::string &key, std::uint32_t mode,
|
||||
std::uint64_t modified_date, std::uint32_t osx_backup,
|
||||
std::uint32_t osx_flags, std::uint64_t size, const std::string &source_path,
|
||||
std::uint32_t uid, std::uint64_t written_date) -> api_meta_map {
|
||||
return {
|
||||
{META_ACCESSED, std::to_string(accessed_date)},
|
||||
{META_ATTRIBUTES, std::to_string(attributes)},
|
||||
@ -197,7 +196,6 @@ auto create_meta_attributes(
|
||||
{META_CHANGED, std::to_string(changed_date)},
|
||||
{META_CREATION, std::to_string(creation_date)},
|
||||
{META_DIRECTORY, utils::string::from_bool(directory)},
|
||||
{META_ENCRYPTION_TOKEN, encryption_token},
|
||||
{META_GID, std::to_string(gid)},
|
||||
{META_KEY, key},
|
||||
{META_MODE, std::to_string(mode)},
|
||||
@ -217,8 +215,7 @@ auto provider_meta_handler(i_provider &provider, bool directory,
|
||||
file.accessed_date,
|
||||
directory ? FILE_ATTRIBUTE_DIRECTORY
|
||||
: FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE,
|
||||
file.changed_date, file.creation_date, directory, file.encryption_token,
|
||||
getgid(), file.key,
|
||||
file.changed_date, file.creation_date, directory, getgid(), file.key,
|
||||
directory ? S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR
|
||||
: S_IFREG | S_IRUSR | S_IWUSR,
|
||||
file.modified_date, 0u, 0u, file.file_size, file.source_path, getuid(),
|
||||
|
@ -166,11 +166,10 @@ auto lock_data::set_mount_state(bool active, const std::string &mount_location,
|
||||
auto create_meta_attributes(
|
||||
std::uint64_t accessed_date, std::uint32_t attributes,
|
||||
std::uint64_t changed_date, std::uint64_t creation_date, bool directory,
|
||||
const std::string &encryption_token, std::uint32_t gid,
|
||||
const std::string &key, std::uint32_t mode, std::uint64_t modified_date,
|
||||
std::uint32_t osx_backup, std::uint32_t osx_flags, std::uint64_t size,
|
||||
const std::string &source_path, std::uint32_t uid,
|
||||
std::uint64_t written_date) -> api_meta_map {
|
||||
std::uint32_t gid, const std::string &key, std::uint32_t mode,
|
||||
std::uint64_t modified_date, std::uint32_t osx_backup,
|
||||
std::uint32_t osx_flags, std::uint64_t size, const std::string &source_path,
|
||||
std::uint32_t uid, std::uint64_t written_date) -> api_meta_map {
|
||||
return {
|
||||
{META_ACCESSED, std::to_string(accessed_date)},
|
||||
{META_ATTRIBUTES, std::to_string(attributes)},
|
||||
@ -178,7 +177,6 @@ auto create_meta_attributes(
|
||||
{META_CHANGED, std::to_string(changed_date)},
|
||||
{META_CREATION, std::to_string(creation_date)},
|
||||
{META_DIRECTORY, utils::string::from_bool(directory)},
|
||||
{META_ENCRYPTION_TOKEN, encryption_token},
|
||||
{META_GID, std::to_string(gid)},
|
||||
{META_KEY, key},
|
||||
{META_MODE, std::to_string(mode)},
|
||||
@ -198,9 +196,9 @@ auto provider_meta_handler(i_provider &provider, bool directory,
|
||||
file.accessed_date,
|
||||
directory ? FILE_ATTRIBUTE_DIRECTORY
|
||||
: FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE,
|
||||
file.changed_date, file.creation_date, directory, file.encryption_token,
|
||||
0u, file.key, directory ? S_IFDIR : S_IFREG, file.modified_date, 0u, 0u,
|
||||
file.file_size, file.source_path, 0u, file.modified_date);
|
||||
file.changed_date, file.creation_date, directory, 0u, file.key,
|
||||
directory ? S_IFDIR : S_IFREG, file.modified_date, 0u, 0u, file.file_size,
|
||||
file.source_path, 0u, file.modified_date);
|
||||
auto res = provider.set_item_meta(file.api_path, meta);
|
||||
if (res == api_error::success) {
|
||||
event_system::instance().raise<filesystem_item_added>(
|
||||
|
@ -22,62 +22,70 @@
|
||||
#include "providers/base_provider.hpp"
|
||||
|
||||
#include "app_config.hpp"
|
||||
#include "events/event_system.hpp"
|
||||
#include "events/events.hpp"
|
||||
#include "file_manager/i_file_manager.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "types/startup_exception.hpp"
|
||||
#include "utils/error_utils.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/native_file.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
#include "utils/polling.hpp"
|
||||
#include "utils/rocksdb_utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
base_provider::base_provider(app_config &config) : config_(config) {}
|
||||
|
||||
void base_provider::calculate_used_drive_space(bool add_missing) {
|
||||
api_file_list list{};
|
||||
if (get_file_list(list) != api_error::success) {
|
||||
return;
|
||||
}
|
||||
|
||||
used_space_ = std::accumulate(
|
||||
list.begin(), list.end(), std::uint64_t(0U),
|
||||
[this, &add_missing](std::uint64_t total_size, const auto &file) {
|
||||
if (add_missing && not meta_db_->get_item_meta_exists(file.api_path)) {
|
||||
[[maybe_unused]] auto res = this->notify_file_added(
|
||||
file.api_path, utils::path::get_parent_api_path(file.api_path),
|
||||
0);
|
||||
}
|
||||
|
||||
return total_size + file.file_size;
|
||||
});
|
||||
auto base_provider::create_api_file(std::string path, std::string key,
|
||||
std::uint64_t size) -> api_file {
|
||||
api_file file{};
|
||||
file.api_path = utils::path::create_api_path(path);
|
||||
file.api_parent = utils::path::get_parent_api_path(file.api_path);
|
||||
file.accessed_date = utils::get_file_time_now();
|
||||
file.changed_date = utils::get_file_time_now();
|
||||
file.creation_date = utils::get_file_time_now();
|
||||
file.modified_date = utils::get_file_time_now();
|
||||
file.key = key;
|
||||
file.file_size = size;
|
||||
return file;
|
||||
}
|
||||
|
||||
void base_provider::cleanup() {
|
||||
remove_deleted_files();
|
||||
remove_unknown_source_files();
|
||||
remove_expired_orphaned_files();
|
||||
auto base_provider::create_api_file(std::string path, std::uint64_t size,
|
||||
api_meta_map &meta) -> api_file {
|
||||
auto current_size = utils::string::to_uint64(meta[META_SIZE]);
|
||||
if (current_size == 0U) {
|
||||
current_size = size;
|
||||
}
|
||||
|
||||
api_file file{};
|
||||
file.api_path = utils::path::create_api_path(path);
|
||||
file.api_parent = utils::path::get_parent_api_path(file.api_path);
|
||||
file.accessed_date = utils::string::to_uint64(meta[META_ACCESSED]);
|
||||
file.changed_date = utils::string::to_uint64(meta[META_CHANGED]);
|
||||
file.creation_date = utils::string::to_uint64(meta[META_CREATION]);
|
||||
file.file_size = current_size;
|
||||
file.modified_date = utils::string::to_uint64(meta[META_MODIFIED]);
|
||||
return file;
|
||||
}
|
||||
|
||||
auto base_provider::create_directory_clone_source_meta(
|
||||
const std::string &source_api_path, const std::string &api_path)
|
||||
-> api_error {
|
||||
api_meta_map meta{};
|
||||
auto ret = get_item_meta(source_api_path, meta);
|
||||
if (ret == api_error::success) {
|
||||
ret = create_directory(api_path, meta);
|
||||
}
|
||||
return ret == api_error::item_not_found ? api_error::directory_not_found
|
||||
: ret;
|
||||
}
|
||||
|
||||
auto base_provider::create_file(const std::string &api_path, api_meta_map &meta)
|
||||
-> api_error {
|
||||
bool exists{};
|
||||
auto res = is_directory(api_path, exists);
|
||||
auto res = is_file(source_api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
if (exists) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
api_error::item_exists,
|
||||
"failed to create directory");
|
||||
return api_error::item_exists;
|
||||
}
|
||||
|
||||
res = is_directory(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
if (exists) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
api_error::directory_exists,
|
||||
"failed to create directory");
|
||||
return api_error::directory_exists;
|
||||
}
|
||||
|
||||
@ -86,462 +94,433 @@ auto base_provider::create_file(const std::string &api_path, api_meta_map &meta)
|
||||
return res;
|
||||
}
|
||||
if (exists) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
api_error::item_exists,
|
||||
"failed to create directory");
|
||||
return api_error::item_exists;
|
||||
}
|
||||
|
||||
if ((res = meta_db_->set_item_meta(api_path, meta)) != api_error::success) {
|
||||
api_meta_map meta{};
|
||||
res = get_item_meta(source_api_path, meta);
|
||||
if (res != api_error::success) {
|
||||
if (res == api_error::item_not_found) {
|
||||
res = api_error::directory_not_found;
|
||||
}
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res,
|
||||
"failed to create directory");
|
||||
return res;
|
||||
}
|
||||
|
||||
{
|
||||
native_file_ptr nf;
|
||||
res = native_file::create_or_open(meta[META_SOURCE], nf);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
nf->close();
|
||||
}
|
||||
|
||||
stop_type stop_requested = false;
|
||||
return upload_file(api_path, meta[META_SOURCE], meta[META_ENCRYPTION_TOKEN],
|
||||
stop_requested);
|
||||
return create_directory(api_path, meta);
|
||||
}
|
||||
|
||||
auto base_provider::get_api_path_from_source(const std::string &source_path,
|
||||
std::string &api_path) const
|
||||
-> api_error {
|
||||
return meta_db_->get_api_path_from_source(source_path, api_path);
|
||||
}
|
||||
|
||||
auto base_provider::get_directory_items(const std::string &api_path,
|
||||
directory_item_list &list) const
|
||||
-> api_error {
|
||||
auto res = populate_directory_items(api_path, list);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
if (source_path.empty()) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
api_error::item_not_found,
|
||||
"failed to source path from api path");
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
std::sort(list.begin(), list.end(), [](const auto &a, const auto &b) -> bool {
|
||||
return (a.directory && not b.directory) ||
|
||||
(not(b.directory && not a.directory) &&
|
||||
(a.api_path.compare(b.api_path) < 0));
|
||||
});
|
||||
|
||||
list.insert(list.begin(), directory_item{
|
||||
"..",
|
||||
"",
|
||||
true,
|
||||
});
|
||||
list.insert(list.begin(), directory_item{
|
||||
".",
|
||||
"",
|
||||
true,
|
||||
});
|
||||
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto base_provider::get_file(const std::string &api_path, api_file &file) const
|
||||
-> api_error {
|
||||
auto ret = api_error::success;
|
||||
try {
|
||||
if ((ret = populate_file(api_path, file)) != api_error::success) {
|
||||
event_system::instance().raise<file_get_failed>(api_path,
|
||||
api_error_to_string(ret));
|
||||
auto iterator = std::unique_ptr<rocksdb::Iterator>(
|
||||
db_->NewIterator(rocksdb::ReadOptions()));
|
||||
for (iterator->SeekToFirst(); iterator->Valid(); iterator->Next()) {
|
||||
std::string current_source_path{};
|
||||
if (get_item_meta(iterator->key().ToString(), META_SOURCE,
|
||||
current_source_path) != api_error::success) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string sz;
|
||||
if ((ret = get_item_meta(api_path, META_SIZE, sz)) != api_error::success) {
|
||||
return ret;
|
||||
if (current_source_path.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
file.file_size = utils::string::to_uint64(sz);
|
||||
return ret;
|
||||
} catch (const std::exception &e) {
|
||||
event_system::instance().raise<file_get_failed>(
|
||||
api_path, e.what() ? e.what() : "failed to get file");
|
||||
if (current_source_path == source_path) {
|
||||
api_path = iterator->key().ToString();
|
||||
return api_error::success;
|
||||
}
|
||||
}
|
||||
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
auto base_provider::get_file_size(const std::string &api_path,
|
||||
std::uint64_t &file_size) const -> api_error {
|
||||
api_file file{};
|
||||
const auto ret = get_file(api_path, file);
|
||||
if (ret == api_error::success) {
|
||||
file_size = file.file_size;
|
||||
} else {
|
||||
event_system::instance().raise<file_get_size_failed>(
|
||||
api_path, api_error_to_string(ret));
|
||||
}
|
||||
|
||||
return ret;
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
auto base_provider::get_filesystem_item(const std::string &api_path,
|
||||
bool directory,
|
||||
filesystem_item &fsi) const
|
||||
-> api_error {
|
||||
auto ret = api_error::error;
|
||||
if (directory) {
|
||||
bool exists{};
|
||||
ret = is_directory(api_path, exists);
|
||||
if (ret != api_error::success) {
|
||||
return ret;
|
||||
}
|
||||
ret = exists ? api_error::success : api_error::item_not_found;
|
||||
update_filesystem_item(true, ret, api_path, fsi);
|
||||
} else {
|
||||
api_file file{};
|
||||
ret = get_filesystem_item_and_file(api_path, file, fsi);
|
||||
bool exists{};
|
||||
auto res = is_directory(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
if (directory && not exists) {
|
||||
return api_error::directory_not_found;
|
||||
}
|
||||
|
||||
return ret;
|
||||
res = is_file(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
if (not directory && not exists) {
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
api_meta_map meta{};
|
||||
res = get_item_meta(api_path, meta);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
fsi.api_parent = utils::path::get_parent_api_path(api_path);
|
||||
fsi.api_path = api_path;
|
||||
fsi.directory = directory;
|
||||
fsi.size = fsi.directory ? 0U : utils::string::to_uint64(meta[META_SIZE]);
|
||||
fsi.source_path = meta[META_SOURCE];
|
||||
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto base_provider::get_filesystem_item_and_file(const std::string &api_path,
|
||||
api_file &file,
|
||||
filesystem_item &fsi) const
|
||||
-> api_error {
|
||||
auto ret = get_item_meta(api_path, META_SOURCE, fsi.source_path);
|
||||
if (ret == api_error::success) {
|
||||
ret = get_file(api_path, file);
|
||||
if (ret == api_error::success) {
|
||||
fsi.encryption_token = file.encryption_token;
|
||||
fsi.size = file.file_size;
|
||||
} else {
|
||||
bool exists{};
|
||||
ret = is_file(api_path, exists);
|
||||
if (ret != api_error::success) {
|
||||
return ret;
|
||||
}
|
||||
if (not exists) {
|
||||
ret = api_error::item_not_found;
|
||||
}
|
||||
}
|
||||
auto res = get_file(api_path, file);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
update_filesystem_item(false, ret, api_path, fsi);
|
||||
return ret;
|
||||
api_meta_map meta{};
|
||||
res = get_item_meta(api_path, meta);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
fsi.api_parent = utils::path::get_parent_api_path(api_path);
|
||||
fsi.api_path = api_path;
|
||||
fsi.directory = false;
|
||||
fsi.size = utils::string::to_uint64(meta[META_SIZE]);
|
||||
fsi.source_path = meta[META_SOURCE];
|
||||
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto base_provider::get_filesystem_item_from_source_path(
|
||||
const std::string &source_path, filesystem_item &fsi) const -> api_error {
|
||||
auto ret = api_error::item_not_found;
|
||||
if (not source_path.empty()) {
|
||||
std::string api_path;
|
||||
if ((ret = get_api_path_from_source(source_path, api_path)) ==
|
||||
api_error::success) {
|
||||
ret = get_filesystem_item(api_path, false, fsi);
|
||||
}
|
||||
std::string api_path{};
|
||||
auto res = get_api_path_from_source(source_path, api_path);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
return ret;
|
||||
bool exists{};
|
||||
res = is_directory(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
if (exists) {
|
||||
return api_error::directory_exists;
|
||||
}
|
||||
|
||||
return get_filesystem_item(api_path, false, fsi);
|
||||
}
|
||||
|
||||
auto base_provider::get_item_meta(const std::string &api_path,
|
||||
api_meta_map &meta) const -> api_error {
|
||||
auto ret = meta_db_->get_item_meta(api_path, meta);
|
||||
if (ret == api_error::item_not_found) {
|
||||
auto get_meta = false;
|
||||
bool exists{};
|
||||
ret = is_directory(api_path, exists);
|
||||
if (ret != api_error::success) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (exists) {
|
||||
ret = notify_directory_added(api_path,
|
||||
utils::path::get_parent_api_path(api_path));
|
||||
if (ret == api_error::success) {
|
||||
get_meta = true;
|
||||
}
|
||||
} else {
|
||||
ret = is_file(api_path, exists);
|
||||
if (ret != api_error::success) {
|
||||
return ret;
|
||||
}
|
||||
if (exists) {
|
||||
std::uint64_t file_size{};
|
||||
if ((ret = get_file_size(api_path, file_size)) == api_error::success) {
|
||||
get_meta = ((ret = notify_file_added(
|
||||
api_path, utils::path::get_parent_api_path(api_path),
|
||||
file_size)) == api_error::success);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = get_meta ? meta_db_->get_item_meta(api_path, meta)
|
||||
: api_error::item_not_found;
|
||||
std::string meta_value{};
|
||||
db_->Get(rocksdb::ReadOptions(), api_path, &meta_value);
|
||||
if (meta_value.empty()) {
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
return ret;
|
||||
try {
|
||||
meta = json::parse(meta_value).get<api_meta_map>();
|
||||
|
||||
return api_error::success;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
"failed to get item meta");
|
||||
}
|
||||
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
auto base_provider::get_item_meta(const std::string &api_path,
|
||||
const std::string &key,
|
||||
std::string &value) const -> api_error {
|
||||
auto ret = meta_db_->get_item_meta(api_path, key, value);
|
||||
if (ret == api_error::item_not_found) {
|
||||
auto get_meta = false;
|
||||
bool exists{};
|
||||
ret = is_directory(api_path, exists);
|
||||
if (ret != api_error::success) {
|
||||
return ret;
|
||||
}
|
||||
if (exists) {
|
||||
ret = notify_directory_added(api_path,
|
||||
utils::path::get_parent_api_path(api_path));
|
||||
if (ret == api_error::success) {
|
||||
get_meta = true;
|
||||
}
|
||||
} else {
|
||||
ret = is_file(api_path, exists);
|
||||
if (ret != api_error::success) {
|
||||
return ret;
|
||||
}
|
||||
if (exists) {
|
||||
std::uint64_t file_size{};
|
||||
if ((ret = get_file_size(api_path, file_size)) == api_error::success) {
|
||||
get_meta = ((ret = notify_file_added(
|
||||
api_path, utils::path::get_parent_api_path(api_path),
|
||||
file_size)) == api_error::success);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::string meta_value{};
|
||||
db_->Get(rocksdb::ReadOptions(), api_path, &meta_value);
|
||||
if (meta_value.empty()) {
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
ret = get_meta ? meta_db_->get_item_meta(api_path, key, value)
|
||||
: api_error::item_not_found;
|
||||
try {
|
||||
value = json::parse(meta_value)[key];
|
||||
return api_error::success;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
"failed to get item meta");
|
||||
}
|
||||
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
auto base_provider::get_pinned_files() const -> std::vector<std::string> {
|
||||
std::vector<std::string> ret{};
|
||||
|
||||
auto iterator = std::unique_ptr<rocksdb::Iterator>(
|
||||
db_->NewIterator(rocksdb::ReadOptions()));
|
||||
for (iterator->SeekToFirst(); iterator->Valid(); iterator->Next()) {
|
||||
std::string pinned{};
|
||||
if (get_item_meta(iterator->key().ToString(), META_PINNED, pinned) !=
|
||||
api_error::success) {
|
||||
continue;
|
||||
}
|
||||
if (pinned.empty() || not utils::string::to_bool(pinned)) {
|
||||
continue;
|
||||
}
|
||||
ret.emplace_back(iterator->key().ToString());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto base_provider::get_used_drive_space() const -> std::uint64_t {
|
||||
std::uint64_t used_space = used_space_;
|
||||
fm_->update_used_space(used_space);
|
||||
return used_space;
|
||||
auto base_provider::get_total_item_count() const -> std::uint64_t {
|
||||
std::uint64_t ret{};
|
||||
auto iterator = std::unique_ptr<rocksdb::Iterator>(
|
||||
db_->NewIterator(rocksdb::ReadOptions()));
|
||||
for (iterator->SeekToFirst(); iterator->Valid(); iterator->Next()) {
|
||||
ret++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto base_provider::notify_directory_added(const std::string &api_path,
|
||||
const std::string &api_parent)
|
||||
-> api_error {
|
||||
recur_mutex_lock l(notify_added_mutex_);
|
||||
|
||||
const auto now = utils::get_file_time_now();
|
||||
api_file file{};
|
||||
file.api_path = api_path;
|
||||
file.api_parent = api_parent;
|
||||
file.accessed_date = now;
|
||||
file.changed_date = now;
|
||||
file.creation_date = now;
|
||||
file.file_size = 0U;
|
||||
file.modified_date = now;
|
||||
return api_item_added_(true, file);
|
||||
}
|
||||
|
||||
auto base_provider::processed_orphaned_file(const std::string &source_path,
|
||||
const std::string &api_path) const
|
||||
auto base_provider::is_file_writeable(const std::string &api_path) const
|
||||
-> bool {
|
||||
const auto orphaned_directory =
|
||||
utils::path::combine(get_config().get_data_directory(), {"orphaned"});
|
||||
if (utils::file::create_full_directory_path(orphaned_directory)) {
|
||||
event_system::instance().raise<orphaned_file_detected>(source_path);
|
||||
const auto parts = utils::string::split(api_path, '/', false);
|
||||
const auto orphaned_file = utils::path::combine(
|
||||
orphaned_directory, {utils::path::strip_to_file_name(source_path) +
|
||||
'_' + parts[parts.size() - 1U]});
|
||||
|
||||
if (utils::file::reset_modified_time(source_path) &&
|
||||
utils::file::move_file(source_path, orphaned_file)) {
|
||||
event_system::instance().raise<orphaned_file_processed>(source_path,
|
||||
orphaned_file);
|
||||
return true;
|
||||
}
|
||||
|
||||
event_system::instance().raise<orphaned_file_processing_failed>(
|
||||
source_path, orphaned_file,
|
||||
std::to_string(utils::get_last_error_code()));
|
||||
bool exists{};
|
||||
auto res = is_directory(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
utils::error::raise_error(
|
||||
__FUNCTION__, std::to_string(utils::get_last_error_code()),
|
||||
"failed to create orphaned director|sp|" + orphaned_directory);
|
||||
return false;
|
||||
return not exists;
|
||||
}
|
||||
|
||||
void base_provider::remove_deleted_files() {
|
||||
std::vector<std::string> removed_files{};
|
||||
struct removed_item {
|
||||
std::string api_path{};
|
||||
bool directory{};
|
||||
std::string source_path{};
|
||||
};
|
||||
|
||||
api_file_list list{};
|
||||
if (get_file_list(list) == api_error::success) {
|
||||
if (not list.empty()) {
|
||||
auto iterator = meta_db_->create_iterator(false);
|
||||
for (iterator->SeekToFirst(); not stop_requested_ && iterator->Valid();
|
||||
iterator->Next()) {
|
||||
const auto meta_api_path = iterator->key().ToString();
|
||||
if (meta_api_path.empty()) {
|
||||
const auto res = meta_db_->remove_item_meta(meta_api_path);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, meta_api_path, res,
|
||||
"failed to remove item meta");
|
||||
auto res = get_file_list(list);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_error(__FUNCTION__, res, "failed to get file list");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<removed_item> removed_list{};
|
||||
auto iterator = std::unique_ptr<rocksdb::Iterator>(
|
||||
db_->NewIterator(rocksdb::ReadOptions()));
|
||||
for (iterator->SeekToFirst(); iterator->Valid(); iterator->Next()) {
|
||||
api_meta_map meta{};
|
||||
if (get_item_meta(iterator->key().ToString(), meta) == api_error::success) {
|
||||
if (utils::string::to_bool(meta[META_DIRECTORY])) {
|
||||
bool exists{};
|
||||
if (is_directory(iterator->key().ToString(), exists) !=
|
||||
api_error::success) {
|
||||
continue;
|
||||
}
|
||||
if (not exists) {
|
||||
removed_list.emplace_back(
|
||||
removed_item{iterator->key().ToString(), true, ""});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
bool exists{};
|
||||
if (is_file(iterator->key().ToString(), exists) != api_error::success) {
|
||||
continue;
|
||||
}
|
||||
if (not exists) {
|
||||
removed_list.emplace_back(
|
||||
removed_item{iterator->key().ToString(), false, meta[META_SOURCE]});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &item : removed_list) {
|
||||
if (not item.directory) {
|
||||
if (utils::file::is_file(item.source_path)) {
|
||||
const auto orphaned_directory =
|
||||
utils::path::combine(config_.get_data_directory(), {"orphaned"});
|
||||
if (utils::file::create_full_directory_path(orphaned_directory)) {
|
||||
const auto parts = utils::string::split(item.api_path, '/', false);
|
||||
const auto orphaned_file = utils::path::combine(
|
||||
orphaned_directory,
|
||||
{utils::path::strip_to_file_name(item.source_path) + '_' +
|
||||
parts[parts.size() - 1U]});
|
||||
|
||||
event_system::instance().raise<orphaned_file_detected>(
|
||||
item.source_path);
|
||||
if (utils::file::reset_modified_time(item.source_path) &&
|
||||
utils::file::copy_file(item.source_path, orphaned_file)) {
|
||||
event_system::instance().raise<orphaned_file_processed>(
|
||||
item.source_path, orphaned_file);
|
||||
} else {
|
||||
event_system::instance().raise<orphaned_file_processing_failed>(
|
||||
item.source_path, orphaned_file,
|
||||
std::to_string(utils::get_last_error_code()));
|
||||
}
|
||||
} else {
|
||||
auto api_path = meta_api_path;
|
||||
const auto it = std::find_if(list.begin(), list.end(),
|
||||
[&api_path](const auto &file) -> bool {
|
||||
return file.api_path == api_path;
|
||||
});
|
||||
if (it == list.end()) {
|
||||
removed_files.emplace_back(api_path);
|
||||
}
|
||||
utils::error::raise_error(
|
||||
__FUNCTION__, std::to_string(utils::get_last_error_code()),
|
||||
"failed to create orphaned director|sp|" + orphaned_directory);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (not stop_requested_ && not removed_files.empty()) {
|
||||
const auto api_path = removed_files.back();
|
||||
removed_files.pop_back();
|
||||
|
||||
bool exists{};
|
||||
auto res = is_directory(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string source_path;
|
||||
if (not exists &&
|
||||
(check_file_exists(api_path) == api_error::item_not_found) &&
|
||||
(meta_db_->get_item_meta(api_path, META_SOURCE, source_path) ==
|
||||
api_error::success)) {
|
||||
if (not source_path.empty()) {
|
||||
fm_->perform_locked_operation(
|
||||
[this, &api_path, &source_path](i_provider &) -> bool {
|
||||
if (fm_->has_no_open_file_handles()) {
|
||||
const auto res = meta_db_->remove_item_meta(api_path);
|
||||
if (res == api_error::success) {
|
||||
event_system::instance().raise<file_removed_externally>(
|
||||
api_path, source_path);
|
||||
processed_orphaned_file(source_path, api_path);
|
||||
} else {
|
||||
utils::error::raise_api_path_error(
|
||||
__FUNCTION__, api_path, source_path, res,
|
||||
"failed to remove item meta for externally removed file");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
if (fm_->evict_file(item.api_path)) {
|
||||
db_->Delete(rocksdb::WriteOptions(), item.api_path);
|
||||
event_system::instance().raise<file_removed_externally>(
|
||||
item.api_path, item.source_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void base_provider::remove_expired_orphaned_files() {
|
||||
const auto orphaned_directory =
|
||||
utils::path::combine(get_config().get_data_directory(), {"orphaned"});
|
||||
const auto files = utils::file::get_directory_files(orphaned_directory, true);
|
||||
for (const auto &file : files) {
|
||||
if (utils::file::is_modified_date_older_than(
|
||||
file, std::chrono::hours(
|
||||
get_config().get_orphaned_file_retention_days() * 24))) {
|
||||
if (utils::file::retry_delete_file(file)) {
|
||||
event_system::instance().raise<orphaned_file_deleted>(file);
|
||||
}
|
||||
}
|
||||
if (stop_requested_) {
|
||||
break;
|
||||
for (const auto &item : removed_list) {
|
||||
if (item.directory) {
|
||||
db_->Delete(rocksdb::WriteOptions(), item.api_path);
|
||||
event_system::instance().raise<directory_removed_externally>(
|
||||
item.api_path, item.source_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void base_provider::remove_unknown_source_files() {
|
||||
auto files = utils::file::get_directory_files(
|
||||
get_config().get_cache_directory(), true);
|
||||
while (not stop_requested_ && not files.empty()) {
|
||||
const auto file = files.front();
|
||||
files.pop_front();
|
||||
|
||||
std::string api_path;
|
||||
if (not meta_db_->get_source_path_exists(file)) {
|
||||
processed_orphaned_file(file);
|
||||
}
|
||||
auto base_provider::remove_item_meta(const std::string &api_path,
|
||||
const std::string &key) -> api_error {
|
||||
api_meta_map meta{};
|
||||
auto res = get_item_meta(api_path, meta);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
meta.erase(key);
|
||||
|
||||
auto res2 = db_->Put(rocksdb::WriteOptions(), api_path, json(meta).dump());
|
||||
if (not res2.ok()) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res2.code(),
|
||||
"failed to remove item meta");
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto base_provider::rename_file(const std::string &from_api_path,
|
||||
const std::string &to_api_path) -> api_error {
|
||||
std::string source_path;
|
||||
auto ret = get_item_meta(from_api_path, META_SOURCE, source_path);
|
||||
if (ret != api_error::success) {
|
||||
return ret;
|
||||
auto base_provider::set_item_meta(const std::string &api_path,
|
||||
const std::string &key,
|
||||
const std::string &value) -> api_error {
|
||||
json meta_json{};
|
||||
std::string meta_value{};
|
||||
db_->Get(rocksdb::ReadOptions(), api_path, &meta_value);
|
||||
if (not meta_value.empty()) {
|
||||
try {
|
||||
meta_json = json::parse(meta_value);
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
"failed to set item meta");
|
||||
return api_error::error;
|
||||
}
|
||||
}
|
||||
|
||||
std::string encryption_token;
|
||||
ret = get_item_meta(from_api_path, META_ENCRYPTION_TOKEN, encryption_token);
|
||||
if (ret != api_error::success) {
|
||||
return ret;
|
||||
meta_json[key] = value;
|
||||
|
||||
const auto res =
|
||||
db_->Put(rocksdb::WriteOptions(), api_path, meta_json.dump());
|
||||
if (not res.ok()) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res.code(),
|
||||
"failed to set item meta");
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
ret = handle_rename_file(from_api_path, to_api_path, source_path);
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
return ret;
|
||||
auto base_provider::set_item_meta(const std::string &api_path,
|
||||
const api_meta_map &meta) -> api_error {
|
||||
json meta_json{};
|
||||
std::string meta_value{};
|
||||
db_->Get(rocksdb::ReadOptions(), api_path, &meta_value);
|
||||
if (not meta_value.empty()) {
|
||||
try {
|
||||
meta_json = json::parse(meta_value);
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
"failed to set item meta");
|
||||
return api_error::error;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &kv : meta) {
|
||||
meta_json[kv.first] = kv.second;
|
||||
}
|
||||
|
||||
const auto res =
|
||||
db_->Put(rocksdb::WriteOptions(), api_path, meta_json.dump());
|
||||
if (not res.ok()) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res.code(),
|
||||
"failed to set item meta");
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto base_provider::start(api_item_added_callback api_item_added,
|
||||
i_file_manager *fm) -> bool {
|
||||
meta_db_ = std::make_unique<meta_db>(config_);
|
||||
i_file_manager *mgr) -> bool {
|
||||
utils::db::create_rocksdb(config_, DB_NAME, db_);
|
||||
|
||||
api_item_added_ = api_item_added;
|
||||
fm_ = fm;
|
||||
fm_ = mgr;
|
||||
|
||||
api_meta_map meta{};
|
||||
if (get_item_meta("/", meta) == api_error::item_not_found) {
|
||||
auto dir = create_api_file("/", "", 0U);
|
||||
api_item_added_(true, dir);
|
||||
}
|
||||
|
||||
auto online = false;
|
||||
auto unmount_requested = false;
|
||||
{
|
||||
repertory::event_consumer ec(
|
||||
repertory::event_consumer consumer(
|
||||
"unmount_requested",
|
||||
[&unmount_requested](const event &) { unmount_requested = true; });
|
||||
for (std::uint16_t i = 0U; not unmount_requested && not is_online() &&
|
||||
(i < get_config().get_online_check_retry_secs());
|
||||
for (std::uint16_t i = 0U; not online && not unmount_requested &&
|
||||
(i < config_.get_online_check_retry_secs());
|
||||
i++) {
|
||||
event_system::instance().raise<provider_offline>(
|
||||
get_config().get_host_config().host_name_or_ip,
|
||||
get_config().get_host_config().api_port);
|
||||
std::this_thread::sleep_for(1s);
|
||||
online = is_online();
|
||||
if (not online) {
|
||||
event_system::instance().raise<provider_offline>(
|
||||
config_.get_host_config().host_name_or_ip,
|
||||
config_.get_host_config().api_port);
|
||||
std::this_thread::sleep_for(1s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto ret = not unmount_requested && is_online();
|
||||
if (ret) {
|
||||
// Force root creation
|
||||
api_meta_map meta{};
|
||||
auto res = get_item_meta("/", meta);
|
||||
if (res != api_error::success) {
|
||||
throw startup_exception("failed to create root|err|" +
|
||||
api_error_to_string(res));
|
||||
}
|
||||
|
||||
calculate_used_drive_space(false);
|
||||
if (online && not unmount_requested) {
|
||||
polling::instance().set_callback({"check_deleted", polling::frequency::low,
|
||||
[this]() { remove_deleted_files(); }});
|
||||
return true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
void base_provider::stop() { meta_db_.reset(); }
|
||||
|
||||
void base_provider::update_filesystem_item(bool directory,
|
||||
const api_error &error,
|
||||
const std::string &api_path,
|
||||
filesystem_item &fsi) const {
|
||||
if (error == api_error::success) {
|
||||
fsi.directory = directory;
|
||||
fsi.api_path = api_path;
|
||||
fsi.api_parent = utils::path::get_parent_api_path(api_path);
|
||||
} else {
|
||||
event_system::instance().raise<filesystem_item_get_failed>(
|
||||
api_path, std::to_string(static_cast<int>(error)));
|
||||
}
|
||||
void base_provider::stop() {
|
||||
polling::instance().remove_callback("check_deleted");
|
||||
db_.reset();
|
||||
}
|
||||
} // namespace repertory
|
||||
|
@ -33,7 +33,7 @@
|
||||
namespace repertory {
|
||||
encrypt_provider::encrypt_provider(app_config &config) : config_(config) {}
|
||||
|
||||
auto encrypt_provider::create_api_file(const std::string api_path,
|
||||
auto encrypt_provider::create_api_file(const std::string &api_path,
|
||||
bool directory,
|
||||
const std::string &source_path)
|
||||
-> api_file {
|
||||
@ -222,21 +222,23 @@ auto encrypt_provider::get_directory_items(const std::string &api_path,
|
||||
for (const auto &dir_entry :
|
||||
std::filesystem::directory_iterator(source_path)) {
|
||||
try {
|
||||
std::string api_path{};
|
||||
std::string entry_api_path{};
|
||||
if (dir_entry.is_directory()) {
|
||||
db_->Get(rocksdb::ReadOptions(), dir_family_,
|
||||
dir_entry.path().string(), &api_path);
|
||||
if (api_path.empty()) {
|
||||
dir_entry.path().string(), &entry_api_path);
|
||||
if (entry_api_path.empty()) {
|
||||
const auto cfg = config_.get_encrypt_config();
|
||||
for (const auto &child_dir_entry :
|
||||
std::filesystem::directory_iterator(dir_entry.path())) {
|
||||
if (process_directory_entry(child_dir_entry, cfg, api_path)) {
|
||||
api_path = utils::path::get_parent_api_path(api_path);
|
||||
if (process_directory_entry(child_dir_entry, cfg,
|
||||
entry_api_path)) {
|
||||
entry_api_path =
|
||||
utils::path::get_parent_api_path(entry_api_path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (api_path.empty()) {
|
||||
if (entry_api_path.empty()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -246,16 +248,16 @@ auto encrypt_provider::get_directory_items(const std::string &api_path,
|
||||
dir_entry.path().string(), &api_path_data);
|
||||
if (api_path_data.empty()) {
|
||||
const auto cfg = config_.get_encrypt_config();
|
||||
if (not process_directory_entry(dir_entry, cfg, api_path)) {
|
||||
if (not process_directory_entry(dir_entry, cfg, entry_api_path)) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
api_path =
|
||||
entry_api_path =
|
||||
json::parse(api_path_data).at("api_path").get<std::string>();
|
||||
}
|
||||
}
|
||||
|
||||
auto file = create_api_file(api_path, dir_entry.is_directory(),
|
||||
auto file = create_api_file(entry_api_path, dir_entry.is_directory(),
|
||||
dir_entry.path().string());
|
||||
|
||||
directory_item di{};
|
||||
@ -464,13 +466,13 @@ auto encrypt_provider::get_filesystem_item(const std::string &api_path,
|
||||
}
|
||||
|
||||
if (directory) {
|
||||
std::string api_path{};
|
||||
db_->Get(rocksdb::ReadOptions(), dir_family_, source_path, &api_path);
|
||||
if (api_path.empty()) {
|
||||
std::string db_api_path{};
|
||||
db_->Get(rocksdb::ReadOptions(), dir_family_, source_path, &db_api_path);
|
||||
if (db_api_path.empty()) {
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
fsi.api_parent = utils::path::get_parent_api_path(api_path);
|
||||
fsi.api_path = api_path;
|
||||
fsi.api_parent = utils::path::get_parent_api_path(db_api_path);
|
||||
fsi.api_path = db_api_path;
|
||||
fsi.directory = true;
|
||||
fsi.size = 0U;
|
||||
fsi.source_path = source_path;
|
||||
@ -761,7 +763,7 @@ void encrypt_provider::remove_deleted_files() {
|
||||
}
|
||||
|
||||
auto encrypt_provider::start(api_item_added_callback /*api_item_added*/,
|
||||
i_file_manager * /*fm*/) -> bool {
|
||||
i_file_manager * /*mgr*/) -> bool {
|
||||
if (not is_online()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -24,8 +24,6 @@
|
||||
#include "app_config.hpp"
|
||||
#include "comm/curl/curl_comm.hpp"
|
||||
#include "comm/i_http_comm.hpp"
|
||||
#include "comm/i_s3_comm.hpp"
|
||||
#include "comm/s3/s3_comm.hpp"
|
||||
#include "events/events.hpp"
|
||||
#include "providers/encrypt/encrypt_provider.hpp"
|
||||
#include "providers/s3/s3_provider.hpp"
|
||||
@ -51,9 +49,6 @@ auto create_provider(const provider_type &pt, app_config &config)
|
||||
mutex_lock lock(mutex);
|
||||
|
||||
static std::unique_ptr<i_http_comm> comm;
|
||||
#if defined(REPERTORY_ENABLE_S3)
|
||||
static std::unique_ptr<i_s3_comm> s3_comm_;
|
||||
#endif // defined(REPERTORY_ENABLE_S3)
|
||||
|
||||
switch (pt) {
|
||||
case provider_type::sia: {
|
||||
@ -64,9 +59,10 @@ auto create_provider(const provider_type &pt, app_config &config)
|
||||
}
|
||||
#if defined(REPERTORY_ENABLE_S3)
|
||||
case provider_type::s3: {
|
||||
create_comm<i_s3_comm, s3_comm, app_config>(s3_comm_, config);
|
||||
create_comm<i_http_comm, curl_comm, s3_config>(comm,
|
||||
config.get_s3_config());
|
||||
return std::unique_ptr<i_provider>(
|
||||
dynamic_cast<i_provider *>(new s3_provider(config, *s3_comm_)));
|
||||
dynamic_cast<i_provider *>(new s3_provider(config, *comm)));
|
||||
}
|
||||
#endif // defined(REPERTORY_ENABLE_S3)
|
||||
case provider_type::encrypt: {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -23,20 +23,21 @@
|
||||
|
||||
#include "app_config.hpp"
|
||||
#include "comm/i_http_comm.hpp"
|
||||
#include "db/meta_db.hpp"
|
||||
#include "events/events.hpp"
|
||||
#include "file_manager/i_file_manager.hpp"
|
||||
#include "providers/base_provider.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/error_utils.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
#include "utils/polling.hpp"
|
||||
#include "utils/rocksdb_utils.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
sia_provider::sia_provider(app_config &config, i_http_comm &comm)
|
||||
: config_(config), comm_(comm) {}
|
||||
: base_provider(config, comm) {}
|
||||
|
||||
auto sia_provider::get_object_info(const std::string &api_path,
|
||||
json &object_info) const -> api_error {
|
||||
@ -47,22 +48,22 @@ auto sia_provider::get_object_info(const std::string &api_path,
|
||||
|
||||
get.response_handler = [&object_info](const data_buffer &data,
|
||||
long response_code) {
|
||||
if (response_code == 200) {
|
||||
if (response_code == http_error_codes::ok) {
|
||||
object_info = nlohmann::json::parse(data.begin(), data.end());
|
||||
}
|
||||
};
|
||||
|
||||
long response_code{};
|
||||
stop_type stop_requested{};
|
||||
if (not comm_.make_request(get, response_code, stop_requested)) {
|
||||
if (not get_comm().make_request(get, response_code, stop_requested)) {
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
||||
if (response_code == 404) {
|
||||
if (response_code == http_error_codes::not_found) {
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
if (response_code != 200) {
|
||||
if (response_code != http_error_codes::ok) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, response_code,
|
||||
"failed to get object info");
|
||||
return api_error::comm_error;
|
||||
@ -77,7 +78,7 @@ auto sia_provider::get_object_info(const std::string &api_path,
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
auto sia_provider::get_object_list(const std::string api_path,
|
||||
auto sia_provider::get_object_list(const std::string &api_path,
|
||||
nlohmann::json &object_list) const -> bool {
|
||||
curl::requests::http_get get{};
|
||||
get.allow_timeout = true;
|
||||
@ -85,21 +86,21 @@ auto sia_provider::get_object_list(const std::string api_path,
|
||||
|
||||
get.response_handler = [&object_list](const data_buffer &data,
|
||||
long response_code) {
|
||||
if (response_code == 200) {
|
||||
if (response_code == http_error_codes::ok) {
|
||||
object_list = nlohmann::json::parse(data.begin(), data.end());
|
||||
}
|
||||
};
|
||||
|
||||
long response_code{};
|
||||
stop_type stop_requested{};
|
||||
if (not comm_.make_request(get, response_code, stop_requested)) {
|
||||
if (not get_comm().make_request(get, response_code, stop_requested)) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
api_error::comm_error,
|
||||
"failed to get object list");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response_code != 200) {
|
||||
if (response_code != http_error_codes::ok) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, response_code,
|
||||
"failed to get object list");
|
||||
return false;
|
||||
@ -108,37 +109,6 @@ auto sia_provider::get_object_list(const std::string api_path,
|
||||
return true;
|
||||
}
|
||||
|
||||
auto sia_provider::create_api_file(std::string path, std::uint64_t size)
|
||||
-> api_file {
|
||||
api_file file{};
|
||||
file.api_path = utils::path::create_api_path(path);
|
||||
file.api_parent = utils::path::get_parent_api_path(file.api_path);
|
||||
file.accessed_date = utils::get_file_time_now();
|
||||
file.changed_date = utils::get_file_time_now();
|
||||
file.creation_date = utils::get_file_time_now();
|
||||
file.modified_date = utils::get_file_time_now();
|
||||
file.file_size = size;
|
||||
return file;
|
||||
}
|
||||
|
||||
auto sia_provider::create_api_file(std::string path, std::uint64_t size,
|
||||
api_meta_map &meta) -> api_file {
|
||||
auto current_size = utils::string::to_uint64(meta[META_SIZE]);
|
||||
if (current_size == 0U) {
|
||||
current_size = size;
|
||||
}
|
||||
|
||||
api_file file{};
|
||||
file.api_path = utils::path::create_api_path(path);
|
||||
file.api_parent = utils::path::get_parent_api_path(file.api_path);
|
||||
file.accessed_date = utils::string::to_uint64(meta[META_ACCESSED]);
|
||||
file.changed_date = utils::string::to_uint64(meta[META_CHANGED]);
|
||||
file.creation_date = utils::string::to_uint64(meta[META_CREATION]);
|
||||
file.file_size = current_size;
|
||||
file.modified_date = utils::string::to_uint64(meta[META_MODIFIED]);
|
||||
return file;
|
||||
}
|
||||
|
||||
auto sia_provider::create_directory(const std::string &api_path,
|
||||
api_meta_map &meta) -> api_error {
|
||||
bool exists{};
|
||||
@ -166,20 +136,18 @@ auto sia_provider::create_directory(const std::string &api_path,
|
||||
|
||||
try {
|
||||
curl::requests::http_put_file put_file{};
|
||||
put_file.file_name =
|
||||
*(utils::string::split(api_path, '/', false).end() - 1u);
|
||||
put_file.path = "/api/worker/objects" + api_path + "/";
|
||||
|
||||
long response_code{};
|
||||
stop_type stop_requested{};
|
||||
if (not comm_.make_request(put_file, response_code, stop_requested)) {
|
||||
if (not get_comm().make_request(put_file, response_code, stop_requested)) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
api_error::comm_error,
|
||||
"failed to create directory");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
||||
if (response_code != 200) {
|
||||
if (response_code != http_error_codes::ok) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, response_code,
|
||||
"failed to create directory");
|
||||
return api_error::comm_error;
|
||||
@ -194,57 +162,6 @@ auto sia_provider::create_directory(const std::string &api_path,
|
||||
return set_item_meta(api_path, meta);
|
||||
}
|
||||
|
||||
auto sia_provider::create_directory_clone_source_meta(
|
||||
const std::string &source_api_path, const std::string &api_path)
|
||||
-> api_error {
|
||||
bool exists{};
|
||||
auto res = is_file(source_api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
if (exists) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
api_error::item_exists,
|
||||
"failed to create directory");
|
||||
return api_error::item_exists;
|
||||
}
|
||||
|
||||
res = is_directory(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
if (exists) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
api_error::directory_exists,
|
||||
"failed to create directory");
|
||||
return api_error::directory_exists;
|
||||
}
|
||||
|
||||
res = is_file(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
if (exists) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
api_error::item_exists,
|
||||
"failed to create directory");
|
||||
return api_error::item_exists;
|
||||
}
|
||||
|
||||
api_meta_map meta{};
|
||||
res = get_item_meta(source_api_path, meta);
|
||||
if (res != api_error::success) {
|
||||
if (res == api_error::item_not_found) {
|
||||
res = api_error::directory_not_found;
|
||||
}
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res,
|
||||
"failed to create directory");
|
||||
return res;
|
||||
}
|
||||
|
||||
return create_directory(api_path, meta);
|
||||
}
|
||||
|
||||
auto sia_provider::create_file(const std::string &api_path, api_meta_map &meta)
|
||||
-> api_error {
|
||||
bool exists{};
|
||||
@ -272,20 +189,18 @@ auto sia_provider::create_file(const std::string &api_path, api_meta_map &meta)
|
||||
|
||||
try {
|
||||
curl::requests::http_put_file put_file{};
|
||||
put_file.file_name =
|
||||
*(utils::string::split(api_path, '/', false).end() - 1u);
|
||||
put_file.path = "/api/worker/objects" + api_path;
|
||||
|
||||
long response_code{};
|
||||
stop_type stop_requested{};
|
||||
if (not comm_.make_request(put_file, response_code, stop_requested)) {
|
||||
if (not get_comm().make_request(put_file, response_code, stop_requested)) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
api_error::comm_error,
|
||||
"failed to create file");
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
||||
if (response_code != 200) {
|
||||
if (response_code != http_error_codes::ok) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, response_code,
|
||||
"failed to create file");
|
||||
return api_error::comm_error;
|
||||
@ -300,38 +215,6 @@ auto sia_provider::create_file(const std::string &api_path, api_meta_map &meta)
|
||||
return set_item_meta(api_path, meta);
|
||||
}
|
||||
|
||||
auto sia_provider::get_api_path_from_source(const std::string &source_path,
|
||||
std::string &api_path) const
|
||||
-> api_error {
|
||||
if (source_path.empty()) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
api_error::item_not_found,
|
||||
"failed to source path from api path");
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
auto iterator = std::unique_ptr<rocksdb::Iterator>(
|
||||
db_->NewIterator(rocksdb::ReadOptions()));
|
||||
for (iterator->SeekToFirst(); iterator->Valid(); iterator->Next()) {
|
||||
std::string current_source_path{};
|
||||
if (get_item_meta(iterator->key().ToString(), META_SOURCE,
|
||||
current_source_path) != api_error::success) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (current_source_path.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (current_source_path == source_path) {
|
||||
api_path = iterator->key().ToString();
|
||||
return api_error::success;
|
||||
}
|
||||
}
|
||||
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
auto sia_provider::get_directory_item_count(const std::string &api_path) const
|
||||
-> std::uint64_t {
|
||||
try {
|
||||
@ -403,9 +286,9 @@ auto sia_provider::get_directory_items(const std::string &api_path,
|
||||
if (get_item_meta(entry_api_path, meta) ==
|
||||
api_error::item_not_found) {
|
||||
file = create_api_file(
|
||||
entry_api_path,
|
||||
entry_api_path, "",
|
||||
directory ? 0U : entry["size"].get<std::uint64_t>());
|
||||
api_item_added_(directory, file);
|
||||
get_api_item_added()(directory, file);
|
||||
res = get_item_meta(entry_api_path, meta);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_error(__FUNCTION__, res,
|
||||
@ -418,14 +301,14 @@ auto sia_provider::get_directory_items(const std::string &api_path,
|
||||
directory ? 0U : entry["size"].get<std::uint64_t>(), meta);
|
||||
}
|
||||
|
||||
directory_item di{};
|
||||
di.api_parent = file.api_parent;
|
||||
di.api_path = file.api_path;
|
||||
di.directory = directory;
|
||||
di.meta = meta;
|
||||
di.resolved = true;
|
||||
di.size = file.file_size;
|
||||
list.emplace_back(std::move(di));
|
||||
directory_item dir_item{};
|
||||
dir_item.api_parent = file.api_parent;
|
||||
dir_item.api_path = file.api_path;
|
||||
dir_item.directory = directory;
|
||||
dir_item.meta = meta;
|
||||
dir_item.resolved = true;
|
||||
dir_item.size = file.file_size;
|
||||
list.emplace_back(std::move(dir_item));
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
"failed to process entry|" +
|
||||
@ -476,8 +359,8 @@ auto sia_provider::get_file(const std::string &api_path, api_file &file) const
|
||||
|
||||
api_meta_map meta{};
|
||||
if (get_item_meta(api_path, meta) == api_error::item_not_found) {
|
||||
file = create_api_file(api_path, size);
|
||||
api_item_added_(false, file);
|
||||
file = create_api_file(api_path, "", size);
|
||||
get_api_item_added()(false, file);
|
||||
} else {
|
||||
file = create_api_file(api_path, size, meta);
|
||||
}
|
||||
@ -507,8 +390,8 @@ auto sia_provider::get_file_list(api_file_list &list) const -> api_error {
|
||||
api_meta_map meta{};
|
||||
if (get_item_meta(entry_api_path, meta) ==
|
||||
api_error::item_not_found) {
|
||||
auto dir = create_api_file(entry_api_path, 0U);
|
||||
api_item_added_(true, dir);
|
||||
auto dir = create_api_file(entry_api_path, "", 0U);
|
||||
get_api_item_added()(true, dir);
|
||||
}
|
||||
|
||||
auto res = get_files_in_dir(entry_api_path);
|
||||
@ -522,9 +405,9 @@ auto sia_provider::get_file_list(api_file_list &list) const -> api_error {
|
||||
api_meta_map meta{};
|
||||
if (get_item_meta(entry_api_path, meta) ==
|
||||
api_error::item_not_found) {
|
||||
file = create_api_file(entry_api_path,
|
||||
file = create_api_file(entry_api_path, "",
|
||||
entry["size"].get<std::uint64_t>());
|
||||
api_item_added_(false, file);
|
||||
get_api_item_added()(false, file);
|
||||
} else {
|
||||
file = create_api_file(entry_api_path,
|
||||
entry["size"].get<std::uint64_t>(), meta);
|
||||
@ -567,146 +450,6 @@ auto sia_provider::get_file_size(const std::string &api_path,
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto sia_provider::get_filesystem_item(const std::string &api_path,
|
||||
bool directory,
|
||||
filesystem_item &fsi) const
|
||||
-> api_error {
|
||||
bool exists{};
|
||||
auto res = is_directory(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
if (directory && not exists) {
|
||||
return api_error::directory_not_found;
|
||||
}
|
||||
|
||||
res = is_file(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
if (not directory && not exists) {
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
api_meta_map meta{};
|
||||
res = get_item_meta(api_path, meta);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
fsi.api_parent = utils::path::get_parent_api_path(api_path);
|
||||
fsi.api_path = api_path;
|
||||
fsi.directory = directory;
|
||||
fsi.size = fsi.directory ? 0U : utils::string::to_uint64(meta[META_SIZE]);
|
||||
fsi.source_path = meta[META_SOURCE];
|
||||
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto sia_provider::get_filesystem_item_and_file(const std::string &api_path,
|
||||
api_file &file,
|
||||
filesystem_item &fsi) const
|
||||
-> api_error {
|
||||
auto res = get_file(api_path, file);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
api_meta_map meta{};
|
||||
res = get_item_meta(api_path, meta);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
fsi.api_parent = utils::path::get_parent_api_path(api_path);
|
||||
fsi.api_path = api_path;
|
||||
fsi.directory = false;
|
||||
fsi.size = utils::string::to_uint64(meta[META_SIZE]);
|
||||
fsi.source_path = meta[META_SOURCE];
|
||||
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto sia_provider::get_filesystem_item_from_source_path(
|
||||
const std::string &source_path, filesystem_item &fsi) const -> api_error {
|
||||
std::string api_path{};
|
||||
auto res = get_api_path_from_source(source_path, api_path);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
bool exists{};
|
||||
res = is_directory(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
if (exists) {
|
||||
return api_error::directory_exists;
|
||||
}
|
||||
|
||||
return get_filesystem_item(api_path, false, fsi);
|
||||
}
|
||||
|
||||
auto sia_provider::get_item_meta(const std::string &api_path,
|
||||
api_meta_map &meta) const -> api_error {
|
||||
std::string meta_value{};
|
||||
db_->Get(rocksdb::ReadOptions(), api_path, &meta_value);
|
||||
if (meta_value.empty()) {
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
try {
|
||||
meta = json::parse(meta_value).get<api_meta_map>();
|
||||
|
||||
return api_error::success;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
"failed to get item meta");
|
||||
}
|
||||
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
auto sia_provider::get_item_meta(const std::string &api_path,
|
||||
const std::string &key,
|
||||
std::string &value) const -> api_error {
|
||||
std::string meta_value{};
|
||||
db_->Get(rocksdb::ReadOptions(), api_path, &meta_value);
|
||||
if (meta_value.empty()) {
|
||||
return api_error::item_not_found;
|
||||
}
|
||||
|
||||
try {
|
||||
value = json::parse(meta_value)[key];
|
||||
return api_error::success;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
"failed to get item meta");
|
||||
}
|
||||
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
auto sia_provider::get_pinned_files() const -> std::vector<std::string> {
|
||||
std::vector<std::string> ret{};
|
||||
|
||||
auto iterator = std::unique_ptr<rocksdb::Iterator>(
|
||||
db_->NewIterator(rocksdb::ReadOptions()));
|
||||
for (iterator->SeekToFirst(); iterator->Valid(); iterator->Next()) {
|
||||
std::string pinned{};
|
||||
if (get_item_meta(iterator->key().ToString(), META_PINNED, pinned) !=
|
||||
api_error::success) {
|
||||
continue;
|
||||
}
|
||||
if (pinned.empty() || not utils::string::to_bool(pinned)) {
|
||||
continue;
|
||||
}
|
||||
ret.emplace_back(iterator->key().ToString());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto sia_provider::get_total_drive_space() const -> std::uint64_t {
|
||||
try {
|
||||
curl::requests::http_get get{};
|
||||
@ -716,18 +459,18 @@ auto sia_provider::get_total_drive_space() const -> std::uint64_t {
|
||||
json config_data{};
|
||||
get.response_handler = [&config_data](const data_buffer &data,
|
||||
long response_code) {
|
||||
if (response_code == 200) {
|
||||
if (response_code == http_error_codes::ok) {
|
||||
config_data = nlohmann::json::parse(data.begin(), data.end());
|
||||
}
|
||||
};
|
||||
|
||||
long response_code{};
|
||||
stop_type stop_requested{};
|
||||
if (not comm_.make_request(get, response_code, stop_requested)) {
|
||||
if (not get_comm().make_request(get, response_code, stop_requested)) {
|
||||
return 0U;
|
||||
}
|
||||
|
||||
if (response_code != 200) {
|
||||
if (response_code != http_error_codes::ok) {
|
||||
utils::error::raise_error(__FUNCTION__, response_code,
|
||||
"failed to get total drive space");
|
||||
return 0U;
|
||||
@ -742,16 +485,6 @@ auto sia_provider::get_total_drive_space() const -> std::uint64_t {
|
||||
return 0U;
|
||||
}
|
||||
|
||||
auto sia_provider::get_total_item_count() const -> std::uint64_t {
|
||||
std::uint64_t ret{};
|
||||
auto iterator = std::unique_ptr<rocksdb::Iterator>(
|
||||
db_->NewIterator(rocksdb::ReadOptions()));
|
||||
for (iterator->SeekToFirst(); iterator->Valid(); iterator->Next()) {
|
||||
ret++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto sia_provider::get_used_drive_space() const -> std::uint64_t {
|
||||
// TODO adjust size based on open files
|
||||
try {
|
||||
@ -762,25 +495,25 @@ auto sia_provider::get_used_drive_space() const -> std::uint64_t {
|
||||
json object_data{};
|
||||
get.response_handler = [&object_data](const data_buffer &data,
|
||||
long response_code) {
|
||||
if (response_code == 200) {
|
||||
if (response_code == http_error_codes::ok) {
|
||||
object_data = nlohmann::json::parse(data.begin(), data.end());
|
||||
}
|
||||
};
|
||||
|
||||
long response_code{};
|
||||
stop_type stop_requested{};
|
||||
if (not comm_.make_request(get, response_code, stop_requested)) {
|
||||
if (not get_comm().make_request(get, response_code, stop_requested)) {
|
||||
return 0U;
|
||||
}
|
||||
|
||||
if (response_code != 200) {
|
||||
if (response_code != http_error_codes::ok) {
|
||||
utils::error::raise_error(__FUNCTION__, response_code,
|
||||
"failed to get used drive space");
|
||||
return 0U;
|
||||
}
|
||||
|
||||
auto used_space = object_data["totalObjectsSize"].get<std::uint64_t>();
|
||||
fm_->update_used_space(used_space);
|
||||
get_file_mgr()->update_used_space(used_space);
|
||||
return used_space;
|
||||
} catch (const std::exception &ex) {
|
||||
utils::error::raise_error(__FUNCTION__, ex,
|
||||
@ -797,6 +530,8 @@ auto sia_provider::is_directory(const std::string &api_path, bool &exists) const
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
exists = false;
|
||||
|
||||
try {
|
||||
json object_list{};
|
||||
if (not get_object_list(utils::path::get_parent_api_path(api_path),
|
||||
@ -822,34 +557,29 @@ auto sia_provider::is_directory(const std::string &api_path, bool &exists) const
|
||||
auto sia_provider::is_file(const std::string &api_path, bool &exists) const
|
||||
-> api_error {
|
||||
exists = false;
|
||||
|
||||
if (api_path == "/") {
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
json file_data{};
|
||||
auto res = get_object_info(api_path, file_data);
|
||||
if (res == api_error::item_not_found) {
|
||||
try {
|
||||
json file_data{};
|
||||
auto res = get_object_info(api_path, file_data);
|
||||
if (res == api_error::item_not_found) {
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
exists = not file_data.contains("entries");
|
||||
return api_error::success;
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
"failed to determine path is directory");
|
||||
}
|
||||
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
exists = not file_data.contains("entries");
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto sia_provider::is_file_writeable(const std::string &api_path) const
|
||||
-> bool {
|
||||
bool exists{};
|
||||
auto res = is_directory(api_path, exists);
|
||||
if (res != api_error::success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return not exists;
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
auto sia_provider::is_online() const -> bool {
|
||||
@ -861,20 +591,20 @@ auto sia_provider::is_online() const -> bool {
|
||||
json state_data{};
|
||||
get.response_handler = [&state_data](const data_buffer &data,
|
||||
long response_code) {
|
||||
if (response_code == 200) {
|
||||
if (response_code == http_error_codes::ok) {
|
||||
state_data = nlohmann::json::parse(data.begin(), data.end());
|
||||
}
|
||||
};
|
||||
|
||||
long response_code{};
|
||||
stop_type stop_requested{};
|
||||
if (not comm_.make_request(get, response_code, stop_requested)) {
|
||||
if (not get_comm().make_request(get, response_code, stop_requested)) {
|
||||
utils::error::raise_error(__FUNCTION__, api_error::comm_error,
|
||||
"failed to determine if provider is online");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response_code != 200) {
|
||||
if (response_code != http_error_codes::ok) {
|
||||
utils::error::raise_error(__FUNCTION__, response_code,
|
||||
"failed to determine if provider is online");
|
||||
return false;
|
||||
@ -897,25 +627,28 @@ auto sia_provider::read_file_bytes(const std::string &api_path,
|
||||
stop_type &stop_requested) -> api_error {
|
||||
curl::requests::http_get get{};
|
||||
get.path = "/api/worker/objects" + api_path;
|
||||
get.range = {{offset, offset + size - 1U}};
|
||||
get.range = {{
|
||||
offset,
|
||||
offset + size - 1U,
|
||||
}};
|
||||
get.response_handler = [&buffer](const data_buffer &data,
|
||||
long /*response_code*/) { buffer = data; };
|
||||
|
||||
auto res = api_error::comm_error;
|
||||
for (std::uint32_t i = 0U; not stop_requested && res != api_error::success &&
|
||||
i < config_.get_retry_read_count() + 1U;
|
||||
i < get_config().get_retry_read_count() + 1U;
|
||||
i++) {
|
||||
long response_code{};
|
||||
const auto notify_retry = [&]() {
|
||||
if (response_code) {
|
||||
if (response_code == 0) {
|
||||
utils::error::raise_api_path_error(
|
||||
__FUNCTION__, api_path, response_code,
|
||||
__FUNCTION__, api_path, api_error::comm_error,
|
||||
"read file bytes failed|offset|" + std::to_string(offset) +
|
||||
"|size|" + std::to_string(size) + "|retry|" +
|
||||
std::to_string(i + 1U));
|
||||
} else {
|
||||
utils::error::raise_api_path_error(
|
||||
__FUNCTION__, api_path, api_error::comm_error,
|
||||
__FUNCTION__, api_path, response_code,
|
||||
"read file bytes failed|offset|" + std::to_string(offset) +
|
||||
"|size|" + std::to_string(size) + "|retry|" +
|
||||
std::to_string(i + 1U));
|
||||
@ -923,12 +656,13 @@ auto sia_provider::read_file_bytes(const std::string &api_path,
|
||||
std::this_thread::sleep_for(1s);
|
||||
};
|
||||
|
||||
if (not comm_.make_request(get, response_code, stop_requested)) {
|
||||
if (not get_comm().make_request(get, response_code, stop_requested)) {
|
||||
notify_retry();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (response_code < 200 || response_code >= 300) {
|
||||
if (response_code < http_error_codes::ok ||
|
||||
response_code >= http_error_codes::multiple_choices) {
|
||||
notify_retry();
|
||||
continue;
|
||||
}
|
||||
@ -939,99 +673,6 @@ auto sia_provider::read_file_bytes(const std::string &api_path,
|
||||
return res;
|
||||
}
|
||||
|
||||
void sia_provider::remove_deleted_files() {
|
||||
struct removed_item {
|
||||
std::string api_path{};
|
||||
bool directory{};
|
||||
std::string source_path{};
|
||||
};
|
||||
|
||||
api_file_list list{};
|
||||
auto res = get_file_list(list);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_error(__FUNCTION__, res, "failed to get file list");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<removed_item> removed_list{};
|
||||
auto iterator = std::unique_ptr<rocksdb::Iterator>(
|
||||
db_->NewIterator(rocksdb::ReadOptions()));
|
||||
for (iterator->SeekToFirst(); iterator->Valid(); iterator->Next()) {
|
||||
api_meta_map meta{};
|
||||
if (get_item_meta(iterator->key().ToString(), meta) == api_error::success) {
|
||||
if (utils::string::to_bool(meta[META_DIRECTORY])) {
|
||||
bool exists{};
|
||||
auto res = is_directory(iterator->key().ToString(), exists);
|
||||
if (res != api_error::success) {
|
||||
continue;
|
||||
}
|
||||
if (not exists) {
|
||||
removed_list.emplace_back(
|
||||
removed_item{iterator->key().ToString(), true, ""});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
bool exists{};
|
||||
auto res = is_file(iterator->key().ToString(), exists);
|
||||
if (res != api_error::success) {
|
||||
continue;
|
||||
}
|
||||
if (not exists) {
|
||||
removed_list.emplace_back(
|
||||
removed_item{iterator->key().ToString(), false, meta[META_SOURCE]});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &item : removed_list) {
|
||||
if (not item.directory) {
|
||||
if (utils::file::is_file(item.source_path)) {
|
||||
const auto orphaned_directory =
|
||||
utils::path::combine(config_.get_data_directory(), {"orphaned"});
|
||||
if (utils::file::create_full_directory_path(orphaned_directory)) {
|
||||
const auto parts = utils::string::split(item.api_path, '/', false);
|
||||
const auto orphaned_file = utils::path::combine(
|
||||
orphaned_directory,
|
||||
{utils::path::strip_to_file_name(item.source_path) + '_' +
|
||||
parts[parts.size() - 1U]});
|
||||
|
||||
event_system::instance().raise<orphaned_file_detected>(
|
||||
item.source_path);
|
||||
if (utils::file::reset_modified_time(item.source_path) &&
|
||||
utils::file::copy_file(item.source_path, orphaned_file)) {
|
||||
event_system::instance().raise<orphaned_file_processed>(
|
||||
item.source_path, orphaned_file);
|
||||
} else {
|
||||
event_system::instance().raise<orphaned_file_processing_failed>(
|
||||
item.source_path, orphaned_file,
|
||||
std::to_string(utils::get_last_error_code()));
|
||||
}
|
||||
} else {
|
||||
utils::error::raise_error(
|
||||
__FUNCTION__, std::to_string(utils::get_last_error_code()),
|
||||
"failed to create orphaned director|sp|" + orphaned_directory);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (fm_->evict_file(item.api_path)) {
|
||||
db_->Delete(rocksdb::WriteOptions(), item.api_path);
|
||||
event_system::instance().raise<file_removed_externally>(
|
||||
item.api_path, item.source_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &item : removed_list) {
|
||||
if (item.directory) {
|
||||
db_->Delete(rocksdb::WriteOptions(), item.api_path);
|
||||
event_system::instance().raise<directory_removed_externally>(
|
||||
item.api_path, item.source_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto sia_provider::remove_directory(const std::string &api_path) -> api_error {
|
||||
const auto notify_end = [&api_path](api_error error) -> api_error {
|
||||
if (error == api_error::success) {
|
||||
@ -1058,20 +699,20 @@ auto sia_provider::remove_directory(const std::string &api_path) -> api_error {
|
||||
|
||||
long response_code{};
|
||||
stop_type stop_requested{};
|
||||
if (not comm_.make_request(del, response_code, stop_requested)) {
|
||||
if (not get_comm().make_request(del, response_code, stop_requested)) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path,
|
||||
api_error::comm_error,
|
||||
"failed to remove directory");
|
||||
return notify_end(api_error::comm_error);
|
||||
}
|
||||
|
||||
if (response_code != 200) {
|
||||
if (response_code != http_error_codes::ok) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, response_code,
|
||||
"failed to remove directory");
|
||||
return notify_end(api_error::comm_error);
|
||||
}
|
||||
|
||||
auto res2 = db_->Delete(rocksdb::WriteOptions(), api_path);
|
||||
auto res2 = get_db()->Delete(rocksdb::WriteOptions(), api_path);
|
||||
if (not res2.ok()) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res2.code(),
|
||||
"failed to remove directory");
|
||||
@ -1097,7 +738,7 @@ auto sia_provider::remove_file(const std::string &api_path) -> api_error {
|
||||
api_meta_map meta{};
|
||||
auto res = get_item_meta(api_path, meta);
|
||||
|
||||
auto res2 = db_->Delete(rocksdb::WriteOptions(), api_path);
|
||||
auto res2 = get_db()->Delete(rocksdb::WriteOptions(), api_path);
|
||||
if (not res2.ok()) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res2.code(),
|
||||
"failed to remove file");
|
||||
@ -1133,13 +774,14 @@ auto sia_provider::remove_file(const std::string &api_path) -> api_error {
|
||||
|
||||
long response_code{};
|
||||
stop_type stop_requested{};
|
||||
if (not comm_.make_request(del, response_code, stop_requested)) {
|
||||
if (not get_comm().make_request(del, response_code, stop_requested)) {
|
||||
utils::error::raise_api_path_error(
|
||||
__FUNCTION__, api_path, api_error::comm_error, "failed to remove file");
|
||||
return notify_end(api_error::comm_error);
|
||||
}
|
||||
|
||||
if (response_code != 200 && response_code != 404) {
|
||||
if (response_code != http_error_codes::ok &&
|
||||
response_code != http_error_codes::not_found) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, response_code,
|
||||
"failed to remove file");
|
||||
return notify_end(api_error::comm_error);
|
||||
@ -1148,143 +790,26 @@ auto sia_provider::remove_file(const std::string &api_path) -> api_error {
|
||||
return remove_file_meta();
|
||||
}
|
||||
|
||||
auto sia_provider::remove_item_meta(const std::string &api_path,
|
||||
const std::string &key) -> api_error {
|
||||
api_meta_map meta{};
|
||||
auto res = get_item_meta(api_path, meta);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
meta.erase(key);
|
||||
|
||||
auto res2 = db_->Put(rocksdb::WriteOptions(), api_path, json(meta).dump());
|
||||
if (not res2.ok()) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res2.code(),
|
||||
"failed to remove item meta");
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto sia_provider::rename_file(const std::string & /*from_api_path*/,
|
||||
const std::string & /*to_api_path*/)
|
||||
-> api_error {
|
||||
return api_error::not_implemented;
|
||||
}
|
||||
|
||||
auto sia_provider::set_item_meta(const std::string &api_path,
|
||||
const std::string &key,
|
||||
const std::string &value) -> api_error {
|
||||
json meta_json{};
|
||||
std::string meta_value{};
|
||||
db_->Get(rocksdb::ReadOptions(), api_path, &meta_value);
|
||||
if (not meta_value.empty()) {
|
||||
try {
|
||||
meta_json = json::parse(meta_value);
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
"failed to set item meta");
|
||||
return api_error::error;
|
||||
}
|
||||
}
|
||||
|
||||
meta_json[key] = value;
|
||||
|
||||
const auto res =
|
||||
db_->Put(rocksdb::WriteOptions(), api_path, meta_json.dump());
|
||||
if (not res.ok()) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res.code(),
|
||||
"failed to set item meta");
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto sia_provider::set_item_meta(const std::string &api_path,
|
||||
const api_meta_map &meta) -> api_error {
|
||||
json meta_json{};
|
||||
std::string meta_value{};
|
||||
db_->Get(rocksdb::ReadOptions(), api_path, &meta_value);
|
||||
if (not meta_value.empty()) {
|
||||
try {
|
||||
meta_json = json::parse(meta_value);
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, e,
|
||||
"failed to set item meta");
|
||||
return api_error::error;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &kv : meta) {
|
||||
meta_json[kv.first] = kv.second;
|
||||
}
|
||||
|
||||
const auto res =
|
||||
db_->Put(rocksdb::WriteOptions(), api_path, meta_json.dump());
|
||||
if (not res.ok()) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, res.code(),
|
||||
"failed to set item meta");
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
auto sia_provider::start(api_item_added_callback api_item_added,
|
||||
i_file_manager *fm) -> bool {
|
||||
i_file_manager *mgr) -> bool {
|
||||
event_system::instance().raise<service_started>("sia_provider");
|
||||
utils::db::create_rocksdb(config_, DB_NAME, db_);
|
||||
|
||||
api_item_added_ = api_item_added;
|
||||
fm_ = fm;
|
||||
|
||||
api_meta_map meta{};
|
||||
if (get_item_meta("/", meta) == api_error::item_not_found) {
|
||||
auto dir = create_api_file("/", 0U);
|
||||
api_item_added_(true, dir);
|
||||
}
|
||||
|
||||
auto online = false;
|
||||
auto unmount_requested = false;
|
||||
{
|
||||
repertory::event_consumer ec(
|
||||
"unmount_requested",
|
||||
[&unmount_requested](const event &) { unmount_requested = true; });
|
||||
for (std::uint16_t i = 0u; not online && not unmount_requested &&
|
||||
(i < config_.get_online_check_retry_secs());
|
||||
i++) {
|
||||
online = is_online();
|
||||
if (not online) {
|
||||
event_system::instance().raise<provider_offline>(
|
||||
config_.get_host_config().host_name_or_ip,
|
||||
config_.get_host_config().api_port);
|
||||
std::this_thread::sleep_for(1s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (online && not unmount_requested) {
|
||||
polling::instance().set_callback({"check_deleted", polling::frequency::low,
|
||||
[this]() { remove_deleted_files(); }});
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return base_provider::start(api_item_added, mgr);
|
||||
}
|
||||
|
||||
void sia_provider::stop() {
|
||||
event_system::instance().raise<service_shutdown_begin>("sia_provider");
|
||||
polling::instance().remove_callback("check_deleted");
|
||||
db_.reset();
|
||||
base_provider::stop();
|
||||
event_system::instance().raise<service_shutdown_end>("sia_provider");
|
||||
}
|
||||
|
||||
auto sia_provider::upload_file(const std::string &api_path,
|
||||
const std::string &source_path,
|
||||
const std::string & /* encryption_token */,
|
||||
stop_type &stop_requested) -> api_error {
|
||||
event_system::instance().raise<provider_upload_begin>(api_path, source_path);
|
||||
|
||||
@ -1297,20 +822,18 @@ auto sia_provider::upload_file(const std::string &api_path,
|
||||
|
||||
try {
|
||||
curl::requests::http_put_file put_file{};
|
||||
put_file.file_name =
|
||||
*(utils::string::split(api_path, '/', false).end() - 1u);
|
||||
put_file.path = "/api/worker/objects" + api_path;
|
||||
put_file.source_path = source_path;
|
||||
|
||||
long response_code{};
|
||||
if (not comm_.make_request(put_file, response_code, stop_requested)) {
|
||||
if (not get_comm().make_request(put_file, response_code, stop_requested)) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, source_path,
|
||||
api_error::comm_error,
|
||||
"failed to upload file");
|
||||
return notify_end(api_error::comm_error);
|
||||
}
|
||||
|
||||
if (response_code != 200) {
|
||||
if (response_code != http_error_codes::ok) {
|
||||
utils::error::raise_api_path_error(__FUNCTION__, api_path, source_path,
|
||||
response_code,
|
||||
"failed to upload file");
|
||||
|
@ -26,160 +26,92 @@ namespace repertory::remote {
|
||||
auto create_open_flags(std::uint32_t flags) -> open_flags {
|
||||
open_flags ret{};
|
||||
{
|
||||
const auto f = (flags & 3u);
|
||||
ret |= (f == 1u) ? open_flags::write_only
|
||||
: (f == 2u) ? open_flags::read_write
|
||||
: open_flags::read_only;
|
||||
}
|
||||
if (flags & static_cast<std::uint32_t>(O_CREAT)) {
|
||||
ret |= open_flags::create;
|
||||
const auto val = (flags & 3U);
|
||||
ret |= (val == 1U) ? open_flags::write_only
|
||||
: (val == 2U) ? open_flags::read_write
|
||||
: open_flags::read_only;
|
||||
}
|
||||
|
||||
if (flags & static_cast<std::uint32_t>(O_EXCL)) {
|
||||
ret |= open_flags::excl;
|
||||
}
|
||||
const auto set_if_has_flag = [&flags, &ret](auto flag, open_flags o_flag) {
|
||||
if ((flags & static_cast<std::uint32_t>(flag)) != 0U) {
|
||||
ret |= o_flag;
|
||||
}
|
||||
};
|
||||
|
||||
if (flags & static_cast<std::uint32_t>(O_NOCTTY)) {
|
||||
ret |= open_flags::no_ctty;
|
||||
}
|
||||
|
||||
if (flags & static_cast<std::uint32_t>(O_TRUNC)) {
|
||||
ret |= open_flags::truncate;
|
||||
}
|
||||
|
||||
if (flags & static_cast<std::uint32_t>(O_APPEND)) {
|
||||
ret |= open_flags::append;
|
||||
}
|
||||
|
||||
if (flags & static_cast<std::uint32_t>(O_NONBLOCK)) {
|
||||
ret |= open_flags::non_blocking;
|
||||
}
|
||||
|
||||
if (flags & static_cast<std::uint32_t>(O_SYNC)) {
|
||||
ret |= open_flags::sync;
|
||||
}
|
||||
|
||||
if (flags & static_cast<std::uint32_t>(O_ASYNC)) {
|
||||
ret |= open_flags::async;
|
||||
}
|
||||
|
||||
if (flags & static_cast<std::uint32_t>(O_DIRECTORY)) {
|
||||
ret |= open_flags::directory;
|
||||
}
|
||||
|
||||
if (flags & static_cast<std::uint32_t>(O_NOFOLLOW)) {
|
||||
ret |= open_flags::no_follow;
|
||||
}
|
||||
|
||||
if (flags & static_cast<std::uint32_t>(O_CLOEXEC)) {
|
||||
ret |= open_flags::clo_exec;
|
||||
}
|
||||
set_if_has_flag(O_APPEND, open_flags::append);
|
||||
set_if_has_flag(O_ASYNC, open_flags::async);
|
||||
set_if_has_flag(O_CLOEXEC, open_flags::clo_exec);
|
||||
set_if_has_flag(O_CREAT, open_flags::create);
|
||||
#ifdef O_DIRECT
|
||||
if (flags & static_cast<std::uint32_t>(O_DIRECT)) {
|
||||
ret |= open_flags::direct;
|
||||
}
|
||||
#endif
|
||||
#ifdef O_NOATIME
|
||||
if (flags & static_cast<std::uint32_t>(O_NOATIME)) {
|
||||
ret |= open_flags::no_atime;
|
||||
}
|
||||
#endif
|
||||
#ifdef O_PATH
|
||||
if (flags & static_cast<std::uint32_t>(O_PATH)) {
|
||||
ret |= open_flags::path;
|
||||
}
|
||||
#endif
|
||||
#ifdef O_TMPFILE
|
||||
if (flags & static_cast<std::uint32_t>(O_TMPFILE)) {
|
||||
ret |= open_flags::temp_file;
|
||||
}
|
||||
set_if_has_flag(O_DIRECT, open_flags::direct);
|
||||
#endif
|
||||
set_if_has_flag(O_DIRECTORY, open_flags::directory);
|
||||
#ifdef O_DSYNC
|
||||
if (flags & static_cast<std::uint32_t>(O_DSYNC)) {
|
||||
ret |= open_flags::dsync;
|
||||
}
|
||||
set_if_has_flag(O_DSYNC, open_flags::dsync);
|
||||
#endif
|
||||
set_if_has_flag(O_EXCL, open_flags::excl);
|
||||
#ifdef O_NOATIME
|
||||
set_if_has_flag(O_NOATIME, open_flags::no_atime);
|
||||
#endif
|
||||
set_if_has_flag(O_NOCTTY, open_flags::no_ctty);
|
||||
set_if_has_flag(O_NOFOLLOW, open_flags::no_follow);
|
||||
set_if_has_flag(O_NONBLOCK, open_flags::non_blocking);
|
||||
#ifdef O_PATH
|
||||
set_if_has_flag(O_PATH, open_flags::path);
|
||||
#endif
|
||||
set_if_has_flag(O_SYNC, open_flags::sync);
|
||||
#ifdef O_TMPFILE
|
||||
set_if_has_flag(O_TMPFILE, open_flags::temp_file);
|
||||
#endif
|
||||
set_if_has_flag(O_TRUNC, open_flags::truncate);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto create_os_open_flags(const open_flags &flags) -> std::uint32_t {
|
||||
std::uint32_t ret = 0u;
|
||||
if ((flags & open_flags::read_write) == open_flags::read_write) {
|
||||
ret |= static_cast<std::uint32_t>(O_RDWR);
|
||||
} else if ((flags & open_flags::write_only) == open_flags::write_only) {
|
||||
ret |= static_cast<std::uint32_t>(O_WRONLY);
|
||||
} else {
|
||||
ret |= static_cast<std::uint32_t>(O_RDONLY);
|
||||
std::uint32_t ret{};
|
||||
const auto set_if_has_flag = [&flags, &ret](auto o_flag, auto flag) -> bool {
|
||||
if ((flags & o_flag) == o_flag) {
|
||||
ret |= static_cast<std::uint32_t>(flag);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
if (not set_if_has_flag(open_flags::read_write, O_RDWR)) {
|
||||
if (not set_if_has_flag(open_flags::write_only, O_WRONLY)) {
|
||||
ret |= static_cast<std::uint32_t>(O_RDONLY);
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & open_flags::create) == open_flags::create) {
|
||||
ret |= static_cast<std::uint32_t>(O_CREAT);
|
||||
}
|
||||
|
||||
if ((flags & open_flags::excl) == open_flags::excl) {
|
||||
ret |= static_cast<std::uint32_t>(O_EXCL);
|
||||
}
|
||||
|
||||
if ((flags & open_flags::no_ctty) == open_flags::no_ctty) {
|
||||
ret |= static_cast<std::uint32_t>(O_NOCTTY);
|
||||
}
|
||||
|
||||
if ((flags & open_flags::truncate) == open_flags::truncate) {
|
||||
ret |= static_cast<std::uint32_t>(O_TRUNC);
|
||||
}
|
||||
|
||||
if ((flags & open_flags::append) == open_flags::append) {
|
||||
ret |= static_cast<std::uint32_t>(O_APPEND);
|
||||
}
|
||||
|
||||
if ((flags & open_flags::non_blocking) == open_flags::non_blocking) {
|
||||
ret |= static_cast<std::uint32_t>(O_NONBLOCK);
|
||||
}
|
||||
|
||||
if ((flags & open_flags::sync) == open_flags::sync) {
|
||||
ret |= static_cast<std::uint32_t>(O_SYNC);
|
||||
}
|
||||
|
||||
if ((flags & open_flags::async) == open_flags::async) {
|
||||
ret |= static_cast<std::uint32_t>(O_ASYNC);
|
||||
}
|
||||
|
||||
if ((flags & open_flags::directory) == open_flags::directory) {
|
||||
ret |= static_cast<std::uint32_t>(O_DIRECTORY);
|
||||
}
|
||||
|
||||
if ((flags & open_flags::no_follow) == open_flags::no_follow) {
|
||||
ret |= static_cast<std::uint32_t>(O_NOFOLLOW);
|
||||
}
|
||||
|
||||
if ((flags & open_flags::clo_exec) == open_flags::clo_exec) {
|
||||
ret |= static_cast<std::uint32_t>(O_CLOEXEC);
|
||||
}
|
||||
set_if_has_flag(open_flags::append, O_APPEND);
|
||||
set_if_has_flag(open_flags::async, O_ASYNC);
|
||||
set_if_has_flag(open_flags::clo_exec, O_CLOEXEC);
|
||||
set_if_has_flag(open_flags::create, O_CREAT);
|
||||
#ifdef O_DIRECT
|
||||
if ((flags & open_flags::direct) == open_flags::direct) {
|
||||
ret |= static_cast<std::uint32_t>(O_DIRECT);
|
||||
}
|
||||
#endif
|
||||
#ifdef O_NOATIME
|
||||
if ((flags & open_flags::no_atime) == open_flags::no_atime) {
|
||||
ret |= static_cast<std::uint32_t>(O_NOATIME);
|
||||
}
|
||||
#endif
|
||||
#ifdef O_PATH
|
||||
if ((flags & open_flags::path) == open_flags::path) {
|
||||
ret |= static_cast<std::uint32_t>(O_PATH);
|
||||
}
|
||||
#endif
|
||||
#ifdef O_TMPFILE
|
||||
if ((flags & open_flags::temp_file) == open_flags::temp_file) {
|
||||
ret |= static_cast<std::uint32_t>(O_TMPFILE);
|
||||
}
|
||||
set_if_has_flag(open_flags::direct, O_DIRECT);
|
||||
#endif
|
||||
set_if_has_flag(open_flags::directory, O_DIRECTORY);
|
||||
#ifdef O_DSYNC
|
||||
if ((flags & open_flags::dsync) == open_flags::dsync) {
|
||||
ret |= static_cast<std::uint32_t>(O_DSYNC);
|
||||
}
|
||||
set_if_has_flag(open_flags::dsync, O_DSYNC);
|
||||
#endif
|
||||
set_if_has_flag(open_flags::excl, O_EXCL);
|
||||
#ifdef O_NOATIME
|
||||
set_if_has_flag(open_flags::no_atime, O_NOATIME);
|
||||
#endif
|
||||
set_if_has_flag(open_flags::no_ctty, O_NOCTTY);
|
||||
set_if_has_flag(open_flags::no_follow, O_NOFOLLOW);
|
||||
set_if_has_flag(open_flags::non_blocking, O_NONBLOCK);
|
||||
#ifdef O_PATH
|
||||
set_if_has_flag(open_flags::path, O_PATH);
|
||||
#endif
|
||||
set_if_has_flag(open_flags::sync, O_SYNC);
|
||||
#ifdef O_TMPFILE
|
||||
set_if_has_flag(open_flags::temp_file, O_TMPFILE);
|
||||
#endif
|
||||
set_if_has_flag(open_flags::truncate, O_TRUNC);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
@ -31,6 +31,12 @@
|
||||
namespace repertory::utils::encryption {
|
||||
class encrypting_streambuf final : public encrypting_reader::streambuf {
|
||||
public:
|
||||
encrypting_streambuf(const encrypting_streambuf &) = default;
|
||||
encrypting_streambuf(encrypting_streambuf &&) = delete;
|
||||
auto operator=(const encrypting_streambuf &)
|
||||
-> encrypting_streambuf & = delete;
|
||||
auto operator=(encrypting_streambuf &&) -> encrypting_streambuf & = delete;
|
||||
|
||||
explicit encrypting_streambuf(const encrypting_reader &reader)
|
||||
: reader_(reader) {
|
||||
setg(reinterpret_cast<char *>(0), reinterpret_cast<char *>(0),
|
||||
@ -102,7 +108,7 @@ protected:
|
||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(gptr())));
|
||||
|
||||
char c{};
|
||||
const auto res = reader_.reader_function(&c, 1u, 1u, &reader_);
|
||||
const auto res = encrypting_reader::reader_function(&c, 1U, 1U, &reader_);
|
||||
if (res != 1) {
|
||||
return traits_type::eof();
|
||||
}
|
||||
@ -118,7 +124,8 @@ protected:
|
||||
reader_.set_read_position(
|
||||
static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(gptr())));
|
||||
|
||||
const auto res = reader_.reader_function(ptr, 1u, count, &reader_);
|
||||
const auto res = encrypting_reader::reader_function(
|
||||
ptr, 1U, static_cast<std::size_t>(count), &reader_);
|
||||
if ((res == reader_.get_error_return()) ||
|
||||
(reader_.get_stop_requested() && (res == CURL_READFUNC_ABORT))) {
|
||||
return traits_type::eof();
|
||||
@ -126,12 +133,20 @@ protected:
|
||||
|
||||
setg(eback(), gptr() + res,
|
||||
reinterpret_cast<char *>(reader_.get_total_size()));
|
||||
return res;
|
||||
return static_cast<std::streamsize>(res);
|
||||
}
|
||||
};
|
||||
|
||||
class encrypting_reader_iostream final : public encrypting_reader::iostream {
|
||||
public:
|
||||
encrypting_reader_iostream(const encrypting_reader_iostream &) = delete;
|
||||
encrypting_reader_iostream(encrypting_reader_iostream &&) = delete;
|
||||
|
||||
auto operator=(const encrypting_reader_iostream &)
|
||||
-> encrypting_reader_iostream & = delete;
|
||||
auto operator=(encrypting_reader_iostream &&)
|
||||
-> encrypting_reader_iostream & = delete;
|
||||
|
||||
explicit encrypting_reader_iostream(
|
||||
std::unique_ptr<encrypting_streambuf> buffer)
|
||||
: encrypting_reader::iostream(buffer.get()), buffer_(std::move(buffer)) {}
|
||||
@ -146,18 +161,18 @@ const std::size_t encrypting_reader::header_size_ = ([]() {
|
||||
return crypto_aead_xchacha20poly1305_IETF_NPUBBYTES +
|
||||
crypto_aead_xchacha20poly1305_IETF_ABYTES;
|
||||
})();
|
||||
const std::size_t encrypting_reader::data_chunk_size_ = (8u * 1024u * 1024u);
|
||||
const std::size_t encrypting_reader::data_chunk_size_ = (8UL * 1024UL * 1024UL);
|
||||
const std::size_t encrypting_reader::encrypted_chunk_size_ =
|
||||
data_chunk_size_ + header_size_;
|
||||
|
||||
encrypting_reader::encrypting_reader(
|
||||
const std::string &file_name, const std::string &source_path,
|
||||
stop_type &stop_requested, const std::string &token,
|
||||
std::optional<std::string> relative_parent_path, const size_t error_return)
|
||||
std::optional<std::string> relative_parent_path, std::size_t error_return)
|
||||
: key_(utils::encryption::generate_key(token)),
|
||||
stop_requested_(stop_requested),
|
||||
error_return_(error_return) {
|
||||
const auto res = native_file::open(
|
||||
const auto res = native_file::create_or_open(
|
||||
source_path, not relative_parent_path.has_value(), source_file_);
|
||||
if (res != api_error::success) {
|
||||
throw std::runtime_error("file open failed|src|" + source_path + '|' +
|
||||
@ -191,28 +206,27 @@ encrypting_reader::encrypting_reader(
|
||||
file_size, static_cast<std::uint64_t>(data_chunk_size_)));
|
||||
total_size_ =
|
||||
file_size + (total_chunks * encrypting_reader::get_header_size());
|
||||
last_data_chunk_ = total_chunks - 1u;
|
||||
last_data_chunk_ = total_chunks - 1U;
|
||||
last_data_chunk_size_ = static_cast<std::size_t>(
|
||||
(file_size <= data_chunk_size_) ? file_size
|
||||
: (file_size % data_chunk_size_) ? file_size % data_chunk_size_
|
||||
: data_chunk_size_);
|
||||
(file_size <= data_chunk_size_) ? file_size
|
||||
: (file_size % data_chunk_size_) == 0U ? data_chunk_size_
|
||||
: file_size % data_chunk_size_);
|
||||
iv_list_.resize(total_chunks);
|
||||
for (auto &iv : iv_list_) {
|
||||
randombytes_buf(iv.data(), iv.size());
|
||||
}
|
||||
}
|
||||
|
||||
encrypting_reader::encrypting_reader(
|
||||
const std::string &encrypted_file_path, const std::string &source_path,
|
||||
stop_type &stop_requested, const std::string &token,
|
||||
std::vector<
|
||||
std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>
|
||||
iv_list,
|
||||
const size_t error_return)
|
||||
encrypting_reader::encrypting_reader(const std::string &encrypted_file_path,
|
||||
const std::string &source_path,
|
||||
stop_type &stop_requested,
|
||||
const std::string &token,
|
||||
std::size_t error_return)
|
||||
: key_(utils::encryption::generate_key(token)),
|
||||
stop_requested_(stop_requested),
|
||||
error_return_(error_return) {
|
||||
const auto res = native_file::open(source_path, false, source_file_);
|
||||
const auto res =
|
||||
native_file::create_or_open(source_path, false, source_file_);
|
||||
if (res != api_error::success) {
|
||||
throw std::runtime_error("file open failed|src|" + source_path + '|' +
|
||||
api_error_to_string(res));
|
||||
@ -232,27 +246,69 @@ encrypting_reader::encrypting_reader(
|
||||
file_size, static_cast<std::uint64_t>(data_chunk_size_)));
|
||||
total_size_ =
|
||||
file_size + (total_chunks * encrypting_reader::get_header_size());
|
||||
last_data_chunk_ = total_chunks - 1u;
|
||||
last_data_chunk_ = total_chunks - 1U;
|
||||
last_data_chunk_size_ = static_cast<std::size_t>(
|
||||
(file_size <= data_chunk_size_) ? file_size
|
||||
: (file_size % data_chunk_size_) ? file_size % data_chunk_size_
|
||||
: data_chunk_size_);
|
||||
(file_size <= data_chunk_size_) ? file_size
|
||||
: (file_size % data_chunk_size_) == 0U ? data_chunk_size_
|
||||
: file_size % data_chunk_size_);
|
||||
iv_list_.resize(total_chunks);
|
||||
for (auto &iv : iv_list_) {
|
||||
randombytes_buf(iv.data(), iv.size());
|
||||
}
|
||||
}
|
||||
|
||||
encrypting_reader::encrypting_reader(
|
||||
const std::string &encrypted_file_path, const std::string &source_path,
|
||||
stop_type &stop_requested, const std::string &token,
|
||||
std::vector<
|
||||
std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>
|
||||
iv_list,
|
||||
std::size_t error_return)
|
||||
: key_(utils::encryption::generate_key(token)),
|
||||
stop_requested_(stop_requested),
|
||||
error_return_(error_return) {
|
||||
const auto res =
|
||||
native_file::create_or_open(source_path, false, source_file_);
|
||||
if (res != api_error::success) {
|
||||
throw std::runtime_error("file open failed|src|" + source_path + '|' +
|
||||
api_error_to_string(res));
|
||||
}
|
||||
|
||||
encrypted_file_path_ = encrypted_file_path;
|
||||
encrypted_file_name_ =
|
||||
std::filesystem::path(encrypted_file_path_).filename().string();
|
||||
|
||||
std::uint64_t file_size{};
|
||||
if (not utils::file::get_file_size(source_path, file_size)) {
|
||||
throw std::runtime_error("get file size failed|src|" + source_path + '|' +
|
||||
std::to_string(utils::get_last_error_code()));
|
||||
}
|
||||
|
||||
const auto total_chunks = static_cast<std::size_t>(utils::divide_with_ceiling(
|
||||
file_size, static_cast<std::uint64_t>(data_chunk_size_)));
|
||||
total_size_ =
|
||||
file_size + (total_chunks * encrypting_reader::get_header_size());
|
||||
last_data_chunk_ = total_chunks - 1U;
|
||||
last_data_chunk_size_ = static_cast<std::size_t>(
|
||||
(file_size <= data_chunk_size_) ? file_size
|
||||
: (file_size % data_chunk_size_) == 0U ? data_chunk_size_
|
||||
: file_size % data_chunk_size_);
|
||||
iv_list_ = std::move(iv_list);
|
||||
}
|
||||
|
||||
encrypting_reader::encrypting_reader(const encrypting_reader &r)
|
||||
: key_(r.key_),
|
||||
stop_requested_(r.stop_requested_),
|
||||
error_return_(r.error_return_),
|
||||
chunk_buffers_(r.chunk_buffers_),
|
||||
encrypted_file_name_(r.encrypted_file_name_),
|
||||
encrypted_file_path_(r.encrypted_file_path_),
|
||||
iv_list_(r.iv_list_),
|
||||
last_data_chunk_(r.last_data_chunk_),
|
||||
last_data_chunk_size_(r.last_data_chunk_size_),
|
||||
read_offset_(r.read_offset_),
|
||||
source_file_(native_file::clone(r.source_file_)),
|
||||
total_size_(r.total_size_) {}
|
||||
encrypting_reader::encrypting_reader(const encrypting_reader &reader)
|
||||
: key_(reader.key_),
|
||||
stop_requested_(reader.stop_requested_),
|
||||
error_return_(reader.error_return_),
|
||||
chunk_buffers_(reader.chunk_buffers_),
|
||||
encrypted_file_name_(reader.encrypted_file_name_),
|
||||
encrypted_file_path_(reader.encrypted_file_path_),
|
||||
iv_list_(reader.iv_list_),
|
||||
last_data_chunk_(reader.last_data_chunk_),
|
||||
last_data_chunk_size_(reader.last_data_chunk_size_),
|
||||
read_offset_(reader.read_offset_),
|
||||
source_file_(native_file::clone(reader.source_file_)),
|
||||
total_size_(reader.total_size_) {}
|
||||
|
||||
encrypting_reader::~encrypting_reader() {
|
||||
if (source_file_) {
|
||||
|
@ -104,7 +104,7 @@ auto read_encrypted_range(
|
||||
const auto start_chunk =
|
||||
static_cast<std::size_t>(range.begin / data_chunk_size);
|
||||
const auto end_chunk = static_cast<std::size_t>(range.end / data_chunk_size);
|
||||
auto remain = range.end - range.begin + 1u;
|
||||
auto remain = range.end - range.begin + 1U;
|
||||
auto source_offset = static_cast<std::size_t>(range.begin % data_chunk_size);
|
||||
|
||||
for (std::size_t chunk = start_chunk; chunk <= end_chunk; chunk++) {
|
||||
@ -112,8 +112,8 @@ auto read_encrypted_range(
|
||||
const auto start_offset = chunk * encrypted_chunk_size;
|
||||
const auto end_offset = std::min(
|
||||
start_offset + (total_size - (chunk * data_chunk_size)) + header_size -
|
||||
1u,
|
||||
static_cast<std::uint64_t>(start_offset + encrypted_chunk_size - 1u));
|
||||
1U,
|
||||
static_cast<std::uint64_t>(start_offset + encrypted_chunk_size - 1U));
|
||||
|
||||
const auto result = reader(ct, start_offset, end_offset);
|
||||
if (result != api_error::success) {
|
||||
|
@ -61,10 +61,10 @@ auto combine(std::string path, const std::vector<std::string> &paths)
|
||||
return finalize(
|
||||
std::accumulate(paths.begin(), paths.end(), path,
|
||||
[](std::string next_path, const auto &path_part) {
|
||||
if (not next_path.empty()) {
|
||||
next_path += (directory_seperator + path_part);
|
||||
if (next_path.empty()) {
|
||||
return path_part;
|
||||
}
|
||||
return next_path;
|
||||
return next_path + (directory_seperator + path_part);
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "utils/native_file.hpp"
|
||||
#include "utils/path_utils.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include <limits>
|
||||
|
||||
namespace repertory::utils {
|
||||
void calculate_allocation_size(bool directory, std::uint64_t file_size,
|
||||
@ -44,7 +45,7 @@ void calculate_allocation_size(bool directory, std::uint64_t file_size,
|
||||
allocation_size = file_size;
|
||||
}
|
||||
allocation_size =
|
||||
((allocation_size == 0u) ? WINFSP_ALLOCATION_UNIT : allocation_size);
|
||||
((allocation_size == 0U) ? WINFSP_ALLOCATION_UNIT : allocation_size);
|
||||
allocation_size =
|
||||
utils::divide_with_ceiling(allocation_size, WINFSP_ALLOCATION_UNIT) *
|
||||
WINFSP_ALLOCATION_UNIT;
|
||||
@ -55,18 +56,18 @@ auto calculate_read_size(const uint64_t &total_size, std::size_t read_size,
|
||||
const uint64_t &offset) -> std::size_t {
|
||||
return static_cast<std::size_t>(
|
||||
((offset + read_size) > total_size)
|
||||
? ((offset < total_size) ? total_size - offset : 0u)
|
||||
? ((offset < total_size) ? total_size - offset : 0U)
|
||||
: read_size);
|
||||
}
|
||||
|
||||
auto compare_version_strings(std::string version1, std::string version2)
|
||||
-> int {
|
||||
if (utils::string::contains(version1, "-")) {
|
||||
version1 = utils::string::split(version1, '-')[0u];
|
||||
version1 = utils::string::split(version1, '-')[0U];
|
||||
}
|
||||
|
||||
if (utils::string::contains(version2, "-")) {
|
||||
version2 = utils::string::split(version2, '-')[0u];
|
||||
version2 = utils::string::split(version2, '-')[0U];
|
||||
}
|
||||
|
||||
auto nums1 = utils::string::split(version1, '.');
|
||||
@ -80,11 +81,11 @@ auto compare_version_strings(std::string version1, std::string version2)
|
||||
nums1.emplace_back("0");
|
||||
}
|
||||
|
||||
for (std::size_t i = 0u; i < nums1.size(); i++) {
|
||||
for (std::size_t i = 0U; i < nums1.size(); i++) {
|
||||
const auto int1 = utils::string::to_uint32(nums1[i]);
|
||||
const auto int2 = utils::string::to_uint32(nums2[i]);
|
||||
const auto res = std::memcmp(&int1, &int2, sizeof(int1));
|
||||
if (res) {
|
||||
if (res != 0) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@ -105,51 +106,33 @@ auto convert_api_date(const std::string &date) -> std::uint64_t {
|
||||
#else
|
||||
strptime(date_time.c_str(), "%Y-%m-%dT%T", &tm1);
|
||||
#endif
|
||||
return nanos + (mktime(&tm1) * NANOS_PER_SECOND);
|
||||
return nanos + (static_cast<std::uint64_t>(mktime(&tm1)) * NANOS_PER_SECOND);
|
||||
}
|
||||
|
||||
auto create_curl() -> CURL * {
|
||||
static std::recursive_mutex mtx;
|
||||
|
||||
unique_recur_mutex_lock l(mtx);
|
||||
unique_recur_mutex_lock lock(mtx);
|
||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
l.unlock();
|
||||
lock.unlock();
|
||||
|
||||
return reset_curl(curl_easy_init());
|
||||
}
|
||||
|
||||
auto create_uuid_string() -> std::string {
|
||||
#ifdef _WIN32
|
||||
UUID guid{};
|
||||
UuidCreate(&guid);
|
||||
std::random_device random_device;
|
||||
auto seed_data = std::array<int, std::mt19937::state_size>{};
|
||||
std::generate(std::begin(seed_data), std::end(seed_data),
|
||||
std::ref(random_device));
|
||||
std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
|
||||
std::mt19937 generator(seq);
|
||||
uuids::uuid_random_generator gen{generator};
|
||||
|
||||
unsigned char *s;
|
||||
UuidToStringA(&guid, &s);
|
||||
|
||||
std::string ret(reinterpret_cast<char *>(s));
|
||||
RpcStringFreeA(&s);
|
||||
|
||||
return ret;
|
||||
#else
|
||||
#if __linux__
|
||||
uuid id;
|
||||
id.make(UUID_MAKE_V4);
|
||||
return id.string();
|
||||
#else
|
||||
uuid_t guid;
|
||||
uuid_generate_random(guid);
|
||||
|
||||
std::string ret;
|
||||
ret.resize(37);
|
||||
uuid_unparse(guid, &ret[0]);
|
||||
|
||||
return ret.c_str();
|
||||
#endif
|
||||
#endif
|
||||
return uuids::to_string(gen());
|
||||
}
|
||||
|
||||
auto create_volume_label(const provider_type &pt) -> std::string {
|
||||
return "repertory_" + app_config::get_provider_name(pt);
|
||||
auto create_volume_label(const provider_type &prov) -> std::string {
|
||||
return "repertory_" + app_config::get_provider_name(prov);
|
||||
}
|
||||
|
||||
auto download_type_from_string(std::string type,
|
||||
@ -158,9 +141,13 @@ auto download_type_from_string(std::string type,
|
||||
type = utils::string::to_lower(utils::string::trim(type));
|
||||
if (type == "direct") {
|
||||
return download_type::direct;
|
||||
} else if (type == "fallback") {
|
||||
}
|
||||
|
||||
if (type == "fallback") {
|
||||
return download_type::fallback;
|
||||
} else if (type == "ring_buffer") {
|
||||
}
|
||||
|
||||
if (type == "ring_buffer") {
|
||||
return download_type::ring_buffer;
|
||||
}
|
||||
|
||||
@ -186,26 +173,24 @@ auto filetime_to_unix_time(const FILETIME &ft) -> remote::file_time {
|
||||
LARGE_INTEGER date{};
|
||||
date.HighPart = ft.dwHighDateTime;
|
||||
date.LowPart = ft.dwLowDateTime;
|
||||
date.QuadPart -= 116444736000000000ull;
|
||||
date.QuadPart -= 116444736000000000ULL;
|
||||
|
||||
return date.QuadPart * 100ull;
|
||||
return date.QuadPart * 100ULL;
|
||||
}
|
||||
|
||||
void unix_time_to_filetime(const remote::file_time &ts, FILETIME &ft) {
|
||||
const auto winTime = (ts / 100ull) + 116444736000000000ull;
|
||||
ft.dwHighDateTime = winTime >> 32u;
|
||||
ft.dwLowDateTime = winTime & 0xFFFFFFFF;
|
||||
const auto win_time = (ts / 100ULL) + 116444736000000000ULL;
|
||||
ft.dwHighDateTime = win_time >> 32U;
|
||||
ft.dwLowDateTime = win_time & 0xFFFFFFFF;
|
||||
}
|
||||
#endif
|
||||
|
||||
auto generate_random_string(std::uint16_t length) -> std::string {
|
||||
srand(static_cast<unsigned int>(get_time_now()));
|
||||
|
||||
std::string ret;
|
||||
ret.resize(length);
|
||||
for (std::uint16_t i = 0u; i < length; i++) {
|
||||
for (std::uint16_t i = 0U; i < length; i++) {
|
||||
do {
|
||||
ret[i] = static_cast<char>(rand() % 74 + 48);
|
||||
ret[i] = static_cast<char>(repertory_rand<std::uint8_t>() % 74 + 48);
|
||||
} while (((ret[i] >= 91) && (ret[i] <= 96)) ||
|
||||
((ret[i] >= 58) && (ret[i] <= 64)));
|
||||
}
|
||||
@ -218,19 +203,12 @@ auto get_attributes_from_meta(const api_meta_map &meta) -> DWORD {
|
||||
}
|
||||
|
||||
auto get_environment_variable(const std::string &variable) -> std::string {
|
||||
#ifdef _WIN32
|
||||
std::string value;
|
||||
auto sz = ::GetEnvironmentVariable(&variable[0], nullptr, 0);
|
||||
if (sz > 0) {
|
||||
value.resize(sz);
|
||||
::GetEnvironmentVariable(&variable[0], &value[0], sz);
|
||||
}
|
||||
static std::mutex mtx{};
|
||||
mutex_lock lock{mtx};
|
||||
|
||||
return value.c_str();
|
||||
#else
|
||||
const auto *v = getenv(variable.c_str());
|
||||
return std::string(v ? v : "");
|
||||
#endif
|
||||
const auto *val = std::getenv(variable.c_str());
|
||||
auto ret = std::string(val == nullptr ? "" : val);
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto get_file_time_now() -> std::uint64_t {
|
||||
@ -253,8 +231,11 @@ void get_local_time_now(struct tm &local_time) {
|
||||
#ifdef _WIN32
|
||||
localtime_s(&local_time, &now);
|
||||
#else
|
||||
static std::mutex mtx{};
|
||||
mutex_lock lock{mtx};
|
||||
|
||||
const auto *tmp = std::localtime(&now);
|
||||
if (tmp) {
|
||||
if (tmp != nullptr) {
|
||||
memcpy(&local_time, tmp, sizeof(local_time));
|
||||
}
|
||||
#endif
|
||||
@ -264,18 +245,25 @@ auto get_next_available_port(std::uint16_t first_port,
|
||||
std::uint16_t &available_port) -> bool {
|
||||
using namespace boost::asio;
|
||||
using ip::tcp;
|
||||
boost::system::error_code ec;
|
||||
do {
|
||||
io_service svc;
|
||||
tcp::acceptor a(svc);
|
||||
a.open(tcp::v4(), ec) || a.bind({tcp::v4(), first_port}, ec);
|
||||
} while (ec && (first_port++ < 65535u));
|
||||
|
||||
if (not ec) {
|
||||
boost::system::error_code error_code{};
|
||||
while (first_port != 0U) {
|
||||
io_service svc{};
|
||||
tcp::acceptor acceptor(svc);
|
||||
acceptor.open(tcp::v4(), error_code) ||
|
||||
acceptor.bind({tcp::v4(), first_port}, error_code);
|
||||
if (not error_code) {
|
||||
break;
|
||||
}
|
||||
|
||||
++first_port;
|
||||
}
|
||||
|
||||
if (not error_code) {
|
||||
available_port = first_port;
|
||||
}
|
||||
|
||||
return not ec;
|
||||
return not error_code;
|
||||
}
|
||||
|
||||
auto get_time_now() -> std::uint64_t {
|
||||
@ -305,41 +293,44 @@ auto reset_curl(CURL *curl_handle) -> CURL * {
|
||||
}
|
||||
|
||||
auto retryable_action(const std::function<bool()> &action) -> bool {
|
||||
static constexpr const auto retry_count = 20U;
|
||||
|
||||
auto succeeded = false;
|
||||
for (std::uint8_t i = 0u; not(succeeded = action()) && (i < 20u); i++) {
|
||||
for (std::uint8_t i = 0U; not(succeeded = action()) && (i < retry_count);
|
||||
i++) {
|
||||
std::this_thread::sleep_for(100ms);
|
||||
}
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
void spin_wait_for_mutex(std::function<bool()> complete,
|
||||
std::condition_variable &cv, std::mutex &mtx,
|
||||
std::condition_variable &cond, std::mutex &mtx,
|
||||
const std::string &text) {
|
||||
while (not complete()) {
|
||||
unique_mutex_lock l(mtx);
|
||||
unique_mutex_lock lock(mtx);
|
||||
if (not complete()) {
|
||||
if (not text.empty()) {
|
||||
/* event_system::instance().raise<DebugLog>(__FUNCTION__,
|
||||
* "spin_wait_for_mutex", text); */
|
||||
}
|
||||
cv.wait_for(l, 1s);
|
||||
cond.wait_for(lock, 1s);
|
||||
}
|
||||
l.unlock();
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void spin_wait_for_mutex(bool &complete, std::condition_variable &cv,
|
||||
void spin_wait_for_mutex(bool &complete, std::condition_variable &cond,
|
||||
std::mutex &mtx, const std::string &text) {
|
||||
while (not complete) {
|
||||
unique_mutex_lock l(mtx);
|
||||
unique_mutex_lock lock(mtx);
|
||||
if (not complete) {
|
||||
if (not text.empty()) {
|
||||
/* event_system::instance().raise<DebugLog>(__FUNCTION__,
|
||||
* "spin_wait_for_mutex", text); */
|
||||
}
|
||||
cv.wait_for(l, 1s);
|
||||
cond.wait_for(lock, 1s);
|
||||
}
|
||||
l.unlock();
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
} // namespace repertory::utils
|
||||
|
@ -1,321 +0,0 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#include "test_common.hpp"
|
||||
|
||||
#include "fixtures/directory_db_fixture.hpp"
|
||||
|
||||
namespace repertory {
|
||||
static const auto dirs = {"/",
|
||||
"/root",
|
||||
"/root/sub1",
|
||||
"/root/sub2",
|
||||
"/root/sub2/sub2_sub1",
|
||||
"/root/sub2/sub2_sub2",
|
||||
"/root/sub2/sub2_sub2/sub2_sub2_sub1",
|
||||
"/root/sub3"};
|
||||
|
||||
TEST_F(directory_db_test, is_directory) {
|
||||
for (const auto &dir : dirs) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory(dir));
|
||||
}
|
||||
|
||||
for (const auto &dir : dirs) {
|
||||
EXPECT_TRUE(db_->is_directory(dir));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, remove_directory) {
|
||||
for (const auto &dir : dirs) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory(dir));
|
||||
}
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->remove_directory("/root/sub2/sub2_sub1"));
|
||||
EXPECT_FALSE(db_->is_directory("/root/sub2/sub2_sub1"));
|
||||
EXPECT_EQ(1u, db_->get_sub_directory_count("/root/sub2"));
|
||||
EXPECT_TRUE(db_->is_directory("/root/sub2/sub2_sub2"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, get_sub_directory_count) {
|
||||
for (const auto &dir : dirs) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory(dir));
|
||||
}
|
||||
|
||||
EXPECT_EQ(1u, db_->get_sub_directory_count("/"));
|
||||
EXPECT_EQ(3u, db_->get_sub_directory_count("/root"));
|
||||
EXPECT_EQ(0u, db_->get_sub_directory_count("/root/sub1"));
|
||||
EXPECT_EQ(2u, db_->get_sub_directory_count("/root/sub2"));
|
||||
EXPECT_EQ(0u, db_->get_sub_directory_count("/root/sub2/sub2_sub1"));
|
||||
EXPECT_EQ(1u, db_->get_sub_directory_count("/root/sub2/sub2_sub2"));
|
||||
EXPECT_EQ(0u, db_->get_sub_directory_count("/root/sub3"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, populate_sub_directories) {
|
||||
for (const auto &dir : dirs) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory(dir));
|
||||
}
|
||||
|
||||
directory_item_list list{};
|
||||
const auto dump_directory_list = [&]() {
|
||||
for (const auto &di : list) {
|
||||
std::cout << di.to_json().dump(2) << std::endl;
|
||||
}
|
||||
list.clear();
|
||||
};
|
||||
|
||||
std::cout << "/" << std::endl;
|
||||
db_->populate_sub_directories(
|
||||
"/", [](directory_item &) {}, list);
|
||||
EXPECT_EQ(1u, list.size());
|
||||
dump_directory_list();
|
||||
|
||||
std::cout << std::endl << "/root" << std::endl;
|
||||
db_->populate_sub_directories(
|
||||
"/root", [](directory_item &) {}, list);
|
||||
EXPECT_EQ(3u, list.size());
|
||||
dump_directory_list();
|
||||
|
||||
std::cout << std::endl << "/root/sub1" << std::endl;
|
||||
db_->populate_sub_directories(
|
||||
"/root/sub1", [](directory_item &) {}, list);
|
||||
EXPECT_EQ(0u, list.size());
|
||||
dump_directory_list();
|
||||
|
||||
std::cout << std::endl << "/root/sub2" << std::endl;
|
||||
db_->populate_sub_directories(
|
||||
"/root/sub2", [](directory_item &) {}, list);
|
||||
EXPECT_EQ(2u, list.size());
|
||||
dump_directory_list();
|
||||
|
||||
std::cout << std::endl << "/root/sub2/sub2_sub1" << std::endl;
|
||||
db_->populate_sub_directories(
|
||||
"/root/sub2/sub2_sub1", [](directory_item &) {}, list);
|
||||
EXPECT_EQ(0u, list.size());
|
||||
dump_directory_list();
|
||||
|
||||
std::cout << std::endl << "/root/sub2/sub2_sub2" << std::endl;
|
||||
db_->populate_sub_directories(
|
||||
"/root/sub2/sub2_sub2", [](directory_item &) {}, list);
|
||||
EXPECT_EQ(1u, list.size());
|
||||
dump_directory_list();
|
||||
|
||||
std::cout << std::endl << "/root/sub3" << std::endl;
|
||||
db_->populate_sub_directories(
|
||||
"/root/sub3", [](directory_item &) {}, list);
|
||||
EXPECT_EQ(0u, list.size());
|
||||
dump_directory_list();
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, is_file) {
|
||||
for (const auto &dir : dirs) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory(dir));
|
||||
}
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow.txt"));
|
||||
EXPECT_TRUE(db_->is_file("/cow.txt"));
|
||||
EXPECT_FALSE(db_->is_directory("/cow.txt"));
|
||||
EXPECT_EQ(api_error::item_exists, db_->create_file("/cow.txt"));
|
||||
EXPECT_EQ(api_error::item_exists, db_->create_directory("/cow.txt"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, remove_file) {
|
||||
for (const auto &dir : dirs) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory(dir));
|
||||
}
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow.txt"));
|
||||
EXPECT_EQ(api_error::directory_not_found, db_->remove_directory("/cow.txt"));
|
||||
EXPECT_TRUE(db_->remove_file("/cow.txt"));
|
||||
EXPECT_FALSE(db_->is_file("/cow.txt"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, get_directory_item_count) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory("/"));
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow.txt"));
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow2.txt"));
|
||||
EXPECT_EQ(api_error::success, db_->create_directory("/cow"));
|
||||
EXPECT_EQ(3u, db_->get_directory_item_count("/"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, get_file) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory("/"));
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow.txt"));
|
||||
|
||||
api_file file{};
|
||||
EXPECT_EQ(api_error::success,
|
||||
db_->get_file("/cow.txt", file, [](api_file &file) {
|
||||
EXPECT_STREQ("/cow.txt", file.api_path.c_str());
|
||||
}));
|
||||
EXPECT_STREQ("/cow.txt", file.api_path.c_str());
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, get_file_list) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory("/"));
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow.txt"));
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow2.txt"));
|
||||
|
||||
api_file_list list;
|
||||
int i = 0;
|
||||
EXPECT_EQ(api_error::success, db_->get_file_list(list, [&i](api_file &file) {
|
||||
if (i++ == 0) {
|
||||
EXPECT_STREQ("/cow.txt", file.api_path.c_str());
|
||||
} else {
|
||||
EXPECT_STREQ("/cow2.txt", file.api_path.c_str());
|
||||
}
|
||||
}));
|
||||
|
||||
EXPECT_EQ(std::size_t(2u), list.size());
|
||||
EXPECT_STREQ("/cow.txt", list[0u].api_path.c_str());
|
||||
EXPECT_STREQ("/cow2.txt", list[1u].api_path.c_str());
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, get_total_item_count) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory("/"));
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow.txt"));
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow2.txt"));
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->create_directory("/cow"));
|
||||
EXPECT_EQ(api_error::success, db_->create_directory("/cow/moose"));
|
||||
|
||||
EXPECT_EQ(std::uint64_t(5), db_->get_total_item_count());
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, populate_directory_files) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory("/"));
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow.txt"));
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow2.txt"));
|
||||
|
||||
directory_item_list list;
|
||||
int i = 0;
|
||||
db_->populate_directory_files(
|
||||
"/",
|
||||
[&i](directory_item &di) {
|
||||
di.meta[META_SIZE] = std::to_string(i + 1);
|
||||
EXPECT_FALSE(di.directory);
|
||||
if (i++ == 0) {
|
||||
EXPECT_STREQ("/cow.txt", &di.api_path[0]);
|
||||
} else {
|
||||
EXPECT_STREQ("/cow2.txt", &di.api_path[0]);
|
||||
}
|
||||
},
|
||||
list);
|
||||
|
||||
EXPECT_EQ(std::size_t(2u), list.size());
|
||||
|
||||
EXPECT_EQ(1u, list[0].size);
|
||||
EXPECT_STREQ("/cow.txt", &list[0].api_path[0]);
|
||||
|
||||
EXPECT_EQ(2u, list[1].size);
|
||||
EXPECT_STREQ("/cow2.txt", &list[1].api_path[0]);
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, create_directory_fails_if_directory_exists) {
|
||||
for (const auto &dir : dirs) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory(dir));
|
||||
}
|
||||
|
||||
EXPECT_EQ(api_error::directory_exists, db_->create_file("/root/sub1"));
|
||||
EXPECT_TRUE(db_->is_directory("/root/sub1"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, create_file_fails_if_file_exists) {
|
||||
for (const auto &dir : dirs) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory(dir));
|
||||
}
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow.txt"));
|
||||
EXPECT_EQ(api_error::item_exists, db_->create_directory("/cow.txt"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, create_file_fails_if_parent_does_not_exist) {
|
||||
for (const auto &dir : dirs) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory(dir));
|
||||
}
|
||||
|
||||
EXPECT_EQ(api_error::directory_not_found, db_->create_file("/moose/cow.txt"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, create_directory_fails_if_parent_does_not_exist) {
|
||||
for (const auto &dir : dirs) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory(dir));
|
||||
}
|
||||
|
||||
EXPECT_EQ(api_error::directory_not_found, db_->create_file("/cow/moose"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, remove_file_fails_if_directory_exists) {
|
||||
for (const auto &dir : dirs) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory(dir));
|
||||
}
|
||||
|
||||
EXPECT_FALSE(db_->remove_file("/root/sub1"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, remove_directory_fails_if_file_exists) {
|
||||
for (const auto &dir : dirs) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory(dir));
|
||||
}
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/cow.txt"));
|
||||
EXPECT_EQ(api_error::directory_not_found, db_->remove_directory("/cow.txt"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, remove_directory_fails_if_sub_directories_exist) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory("/"));
|
||||
EXPECT_EQ(api_error::success, db_->create_directory("/sub"));
|
||||
EXPECT_EQ(api_error::success, db_->create_directory("/sub/sub2"));
|
||||
|
||||
EXPECT_EQ(api_error::directory_not_empty, db_->remove_directory("/sub"));
|
||||
EXPECT_TRUE(db_->is_directory("/sub"));
|
||||
EXPECT_TRUE(db_->is_directory("/sub/sub2"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test, remove_directory_fails_if_files_exist) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory("/"));
|
||||
EXPECT_EQ(api_error::success, db_->create_directory("/sub"));
|
||||
EXPECT_EQ(api_error::success, db_->create_file("/sub/test.txt"));
|
||||
|
||||
EXPECT_EQ(api_error::directory_not_empty, db_->remove_directory("/sub"));
|
||||
EXPECT_TRUE(db_->is_directory("/sub"));
|
||||
EXPECT_TRUE(db_->is_file("/sub/test.txt"));
|
||||
}
|
||||
|
||||
TEST_F(directory_db_test,
|
||||
remove_directory_fails_for_root_directory_by_default) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory("/"));
|
||||
|
||||
EXPECT_EQ(api_error::access_denied, db_->remove_directory("/"));
|
||||
EXPECT_TRUE(db_->is_directory("/"));
|
||||
}
|
||||
|
||||
TEST_F(
|
||||
directory_db_test,
|
||||
remove_directory_succeeds_for_root_directory_if_allow_remove_root_is_true) {
|
||||
EXPECT_EQ(api_error::success, db_->create_directory("/"));
|
||||
|
||||
EXPECT_EQ(api_error::success, db_->remove_directory("/", true));
|
||||
EXPECT_FALSE(db_->is_directory("/"));
|
||||
}
|
||||
} // namespace repertory
|
@ -81,8 +81,6 @@ TEST(encrypt_provider, can_get_file_list) {
|
||||
list2.at(idx).api_parent.c_str());
|
||||
EXPECT_EQ(list.at(idx).accessed_date, list2.at(idx).accessed_date);
|
||||
EXPECT_EQ(list.at(idx).changed_date, list2.at(idx).changed_date);
|
||||
EXPECT_TRUE(list.at(idx).encryption_token.empty());
|
||||
EXPECT_TRUE(list2.at(idx).encryption_token.empty());
|
||||
EXPECT_EQ(list.at(idx).file_size, list2.at(idx).file_size);
|
||||
EXPECT_TRUE(list.at(idx).key.empty());
|
||||
EXPECT_TRUE(list2.at(idx).key.empty());
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user