v2.1.0-rc (#63)

Reviewed-on: #63
This commit is contained in:
2025-10-16 17:23:36 -05:00
parent 5ab7301cbe
commit f198cd49ee
471 changed files with 24173 additions and 9459 deletions

View File

@@ -5,6 +5,7 @@ _sh_denyrd
_sh_denyrw _sh_denyrw
_spawnv _spawnv
aarch64 aarch64
abcdefgh
advapi32 advapi32
armv8 armv8
autogen autogen
@@ -16,9 +17,12 @@ boost_asio_has_std_string_view
bugprone bugprone
cflags cflags
chrono chrono
clsid
cmake_current_source_dir cmake_current_source_dir
cmdc
coinit_apartmentthreaded coinit_apartmentthreaded
comdlg32 comdlg32
conin$
cppcoreguidelines cppcoreguidelines
cppdbg cppdbg
cppflags cppflags
@@ -27,7 +31,9 @@ cpptrace
cppvsdbg cppvsdbg
create_notraverse create_notraverse
crypto_aead_xchacha20poly1305_ietf_npubbytes crypto_aead_xchacha20poly1305_ietf_npubbytes
cspan
cstdint cstdint
curl_zstd
curle_couldnt_resolve_host curle_couldnt_resolve_host
curlopt_aws_sigv4 curlopt_aws_sigv4
cxxflags cxxflags
@@ -54,6 +60,7 @@ dcurl_staticlib
dcurl_use_libpsl dcurl_use_libpsl
dcurl_use_libssh2 dcurl_use_libssh2
dcurl_zlib dcurl_zlib
dcurl_zstd
ddebug ddebug
decmult_gen_prec_bits decmult_gen_prec_bits
decmult_window_size decmult_window_size
@@ -86,6 +93,7 @@ dspdlog_fmt_external
dthreads_prefer_pthread_flag dthreads_prefer_pthread_flag
dunw_local_only dunw_local_only
duse_libidn2 duse_libidn2
duse_nghttp2
duuid_build_tests duuid_build_tests
dwith_benchmark dwith_benchmark
dwith_gflags dwith_gflags
@@ -97,6 +105,9 @@ endforeach
endfunction endfunction
eventlib eventlib
expect_streq expect_streq
expect_strne
falloc_fl_keep_size
fallocate
fallocate_impl fallocate_impl
fext fext
fgetattr fgetattr
@@ -105,7 +116,10 @@ filebase
flac_version flac_version
flag_nopath flag_nopath
flarge flarge
folderid
fontconfig_version fontconfig_version
foob
fooba
freetype2_version freetype2_version
fsetattr_x fsetattr_x
fusermount fusermount
@@ -118,11 +132,14 @@ gpath
gtest_version gtest_version
has_setxattr has_setxattr
hkey hkey
hresult
httpapi httpapi
httplib httplib
hwnd
icudata icudata
icui18n icui18n
icuuc icuuc
inproc
iostreams iostreams
iphlpapi iphlpapi
ipstream ipstream
@@ -146,8 +163,10 @@ libuuid
libuuid_include_dirs libuuid_include_dirs
libvlc libvlc
linkflags linkflags
llabsll
localappdata localappdata
lpbyte lpbyte
lpthread
lptr lptr
lpwstr lpwstr
markdownlint markdownlint
@@ -158,11 +177,13 @@ msvcr120
msys2 msys2
mtune mtune
musl-libc musl-libc
mwindows
nana nana
ncrypt ncrypt
nlohmann nlohmann
nlohmann_json nlohmann_json
nmakeprg nmakeprg
noappledouble
nohup nohup
nominmax nominmax
ntstatus ntstatus
@@ -171,21 +192,27 @@ nuspell_version
oleaut32 oleaut32
openal_version openal_version
openssldir openssldir
osascript
osxfuse
pistream pistream
pkgconfig pkgconfig
plarge_integer plarge_integer
plex plex
posix
println println
project_enable_fontconfig project_enable_fontconfig
project_enable_gtkmm project_enable_gtkmm
project_enable_libdsm project_enable_libdsm
project_enable_nana project_enable_nana
project_macos_icns_name
propgrid propgrid
psecurity_descriptor psecurity_descriptor
pthreads
pugi pugi
pugixml_project pugixml_project
puint32 puint32
pvoid pvoid
pwhash
pwstr pwstr
rdrw rdrw
remote_winfsp remote_winfsp
@@ -193,13 +220,16 @@ renterd
richtext richtext
rocksdb_library rocksdb_library
rpcrt4 rpcrt4
runas
s_igid s_igid
s_isvtx s_isvtx
s_iuid s_iuid
sddl_revision_1 sddl_revision_1
secp256k1 secp256k1
secur32 secur32
see_mask_nocloseprocess
sfml_project sfml_project
shellexecuteinfoa
shlwapi shlwapi
sigchld sigchld
skynet skynet
@@ -207,11 +237,14 @@ source_subdir
spdlog spdlog
spdlog_project spdlog_project
st_ctim st_ctim
startf_useshowwindow
startupinfoa
static-libgcc static-libgcc
static-libstdc++ static-libstdc++
stbuf stbuf
stduuid_project stduuid_project
strequal strequal
sw_shownoactivate
ularge_integer ularge_integer
uring uring
url url
@@ -230,6 +263,7 @@ wextra
wfloat wfloat
wformat=2 wformat=2
winfsp winfsp
winfsp_drive
winhttp winhttp
wininet wininet
winspool winspool

3
.gitattributes vendored
View File

@@ -1,4 +1,5 @@
*.tgz filter=lfs diff=lfs merge=lfs -text *.msi filter=lfs diff=lfs merge=lfs -text
*.tar.gz filter=lfs diff=lfs merge=lfs -text *.tar.gz filter=lfs diff=lfs merge=lfs -text
*.tar.xz filter=lfs diff=lfs merge=lfs -text *.tar.xz filter=lfs diff=lfs merge=lfs -text
*.tgz filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text *.zip filter=lfs diff=lfs merge=lfs -text

13
.gitignore vendored
View File

@@ -1,13 +1,16 @@
.DS_Store
.cache/ .cache/
.vs/
Info.plist
build*/ build*/
compile_commands.json compile_commands.json
cspell.json cspell.json
.vs/
support/Dockerfile
dist/
deps/ deps/
dist/
override.sh
repertory.iss
scripts/cleanup.cmd scripts/cleanup.cmd
scripts/cleanup.sh scripts/cleanup.sh
version.rc support/Dockerfile
version.cpp version.cpp
override.sh version.rc

View File

@@ -6,56 +6,87 @@ pipeline {
environment { environment {
DEVELOPER_PRIVATE_KEY = "/.ci/repertory/cert/developer.priv" DEVELOPER_PRIVATE_KEY = "/.ci/repertory/cert/developer.priv"
DEVELOPER_PUBLIC_KEY = "/.ci/repertory/cert/developer.pub" DEVELOPER_PUBLIC_KEY = "/.ci/repertory/cert/developer.pub"
PROJECT_TEST_CONFIG_DIR = "/.ci/repertory/test_config" PROJECT_TEST_CONFIG_DIR = "/.ci/repertory/test"
} }
options { options {
disableConcurrentBuilds() disableConcurrentBuilds()
retry(2) skipDefaultCheckout()
timestamps()
} }
stages { stages {
stage('linux_x86_64') { stage('Build • Test • Deliver') {
agent any agent any
stages {
stage('Checkout') {
steps { steps {
retry(2) { script {
sleep time: 5, unit: 'SECONDS' int maxAttempts = 6
sh 'scripts/make_unix.sh' int baseDelay = 10
for (int attempt = 1; attempt <= maxAttempts; attempt++) {
try {
checkout scm
break
} catch (err) {
if (attempt == maxAttempts) { throw err }
int waitSec = baseDelay * (1 << (attempt - 1))
echo "Checkout failed (attempt ${attempt}/${maxAttempts}). Waiting ${waitSec}s before retry..."
sleep time: waitSec, unit: 'SECONDS'
} }
} }
} }
}
}
stage('linux_x86_64') {
steps {
script { retryWithBackoff(2, 5) { sh 'scripts/make_unix.sh' } }
}
}
stage('mingw64') { stage('mingw64') {
agent any
steps { steps {
retry(2) { script { retryWithBackoff(2, 5) { sh 'scripts/make_win32.sh' } }
sleep time: 5, unit: 'SECONDS'
sh 'scripts/make_win32.sh'
}
} }
} }
stage('linux_aarch64') { stage('linux_aarch64') {
agent any
steps { steps {
retry(2) { script { retryWithBackoff(2, 5) { sh 'scripts/make_unix.sh aarch64' } }
sleep time: 5, unit: 'SECONDS'
sh 'scripts/make_unix.sh aarch64'
} }
} }
stage('linux_x86_64_test') {
steps {
script { retryWithBackoff(2, 5) { sh 'scripts/run_tests.sh' } }
}
} }
stage('deliver') { stage('deliver') {
agent any
steps { steps {
sh 'scripts/deliver.sh /mnt/repertory "" "" "" "" 1 1' script {
sh 'scripts/deliver.sh /mnt/repertory "" aarch64' retryWithBackoff(3, 10) { sh 'scripts/deliver.sh /mnt/repertory "" "" "" "" 1 1' }
sh 'scripts/deliver.sh /mnt/repertory' retryWithBackoff(3, 10) { sh 'scripts/deliver.sh /mnt/repertory "" aarch64' }
retryWithBackoff(3, 10) { sh 'scripts/deliver.sh /mnt/repertory' }
}
}
}
} }
} }
} }
} }
def retryWithBackoff(int maxAttempts, int baseDelaySeconds, Closure body) {
for (int attempt = 1; attempt <= maxAttempts; attempt++) {
try {
body()
return
} catch (err) {
if (attempt == maxAttempts) { throw err }
int waitSec = baseDelaySeconds * (1 << (attempt - 1))
echo "Step failed (attempt ${attempt}/${maxAttempts}). Waiting ${waitSec}s before retry..."
sleep time: waitSec, unit: 'SECONDS'
}
}
}

79
.jenkins_macos Normal file
View File

@@ -0,0 +1,79 @@
#!groovy
pipeline {
agent none
environment {
DEVELOPER_PRIVATE_KEY = "${env.HOME}/.ci/repertory/cert/developer.priv"
DEVELOPER_PUBLIC_KEY = "${env.HOME}/.ci/repertory/cert/developer.pub"
PROJECT_TEST_CONFIG_DIR = "${env.HOME}/.ci/repertory/test"
}
options {
disableConcurrentBuilds()
skipDefaultCheckout()
timestamps()
}
stages {
stage('Build • Test • Deliver') {
agent any
stages {
stage('Checkout') {
steps {
script {
int maxAttempts = 6
int baseDelay = 10
for (int attempt = 1; attempt <= maxAttempts; attempt++) {
try {
checkout scm
break
} catch (err) {
if (attempt == maxAttempts) { throw err }
int waitSec = baseDelay * (1 << (attempt - 1))
echo "Checkout failed (attempt ${attempt}/${maxAttempts}). Waiting ${waitSec}s before retry..."
sleep time: waitSec, unit: 'SECONDS'
}
}
}
}
}
stage('darwin_aarch64') {
steps { script { retryWithBackoff(2, 5) { sh 'scripts/make_unix.sh aarch64' } } }
}
stage('darwin_x86_64') {
steps { script { retryWithBackoff(2, 5) { sh 'scripts/make_unix.sh x86_64' } } }
}
stage('darwin_aarch64_test') {
steps { script { retryWithBackoff(2, 5) { sh 'scripts/run_tests.sh aarch64' } } }
}
stage('deliver') {
steps {
script {
retryWithBackoff(3, 10) { sh "scripts/deliver.sh ${env.HOME}/mnt/repertory '' aarch64" }
retryWithBackoff(3, 10) { sh "scripts/deliver.sh ${env.HOME}/mnt/repertory '' x86_64" }
}
}
}
}
}
}
}
def retryWithBackoff(int maxAttempts, int baseDelaySeconds, Closure body) {
for (int attempt = 1; attempt <= maxAttempts; attempt++) {
try {
body()
return
} catch (err) {
if (attempt == maxAttempts) { throw err }
int waitSec = baseDelaySeconds * (1 << (attempt - 1))
echo "Step failed (attempt ${attempt}/${maxAttempts}). Waiting ${waitSec}s before retry..."
sleep time: waitSec, unit: 'SECONDS'
}
}
}

68
.jenkins_msys2 Normal file
View File

@@ -0,0 +1,68 @@
#!groovy
pipeline {
agent none
environment {
PROJECT_TEST_CONFIG_DIR = "c:\\.ci\\repertory\\test"
}
options {
disableConcurrentBuilds()
skipDefaultCheckout()
timestamps()
}
stages {
stage('Build • Test') {
agent any
stages {
stage('Checkout') {
steps {
script {
int maxAttempts = 6
int baseDelay = 10
for (int attempt = 1; attempt <= maxAttempts; attempt++) {
try {
checkout scm
break
} catch (err) {
if (attempt == maxAttempts) { throw err }
int waitSec = baseDelay * (1 << (attempt - 1))
echo "Checkout failed (attempt ${attempt}/${maxAttempts}). Waiting ${waitSec}s before retry..."
sleep time: waitSec, unit: 'SECONDS'
}
}
}
}
}
stage('msys2') {
steps {
script { retryWithBackoff(2, 5) { bat 'scripts\\make_win32.cmd' } }
}
}
// stage('msys2_test') {
// steps {
// script { retryWithBackoff(2, 5) { bat 'scripts\\run_tests.cmd' } }
// }
// }
}
}
}
}
def retryWithBackoff(int maxAttempts, int baseDelaySeconds, Closure body) {
for (int attempt = 1; attempt <= maxAttempts; attempt++) {
try {
body()
return
} catch (err) {
if (attempt == maxAttempts) { throw err }
int waitSec = baseDelaySeconds * (1 << (attempt - 1))
echo "Step failed (attempt ${attempt}/${maxAttempts}). Waiting ${waitSec}s before retry..."
sleep time: waitSec, unit: 'SECONDS'
}
}
}

View File

@@ -1,14 +1,55 @@
# Changelog # Changelog
## v2.1.0-rc
### BREAKING CHANGES
* Mount state has been moved into the configuration directory
* Unmount all active mounts prior to upgrade
* Remote mounts must be upgraded to v2.1.0+ to support new authentication scheme
* Protocol handshake added for DoS protection
### Issues
* \#12 [unit test] Complete all providers unit tests
* \#22 [unit test] Complete FUSE unit tests
* \#33 Complete initial v2.0 documentation
* \#34 Add macOS support
* \#38 Pinning a file should automatically initiate a download to cache
* \#51 [ui] UI console window should close after launch
* \#52 [ui] Add auto-mount on first launch functionality
* \#53 Create Windows installer
* \#54 Remove 'default' as initial bucket name for Sia
* \#58 Create macOS bundle for simplified installation
* \#59 [bug] [ui] UI is hanging after launching repertory mount in background
* \#60 Implement secure key via KDF for transparent data encryption/decryption
* \#61 [ui] UI theme should match repertory blue
### Changes from v2.0.7-release
* Added check version support to remote mounts
* Fixed directory item count bug on S3 provider
* Fixed handling of `FALLOC_FL_KEEP_SIZE` on Linux
* Fixed intermittent client hang on remote mount server disconnect
* Implemented POSIX-compliant `unlink()` with FUSE `hard_remove`
* Open handles remain valid after `unlink()`
* Refactored CLI messages and error handling to use common methods
* Enhanced remote mount client thread mapping
* Threads are now mapped 1-1 from client to server instead of being tied to a fixed-size thread pool
## v2.0.7-release ## v2.0.7-release
<!-- markdownlint-disable-next-line -->
### Issues ### Issues
* \#55 [bug] UI is unable to launch `repertory.exe` on Windows when absolute path contains spaces * \#55 [bug] UI is unable to launch `repertory.exe` on Windows when absolute path contains spaces
* \#57 [bug] Directory entries . and .. are incorrectly being reported as files in Linux remote mounts * \#57 [bug] Directory entries . and .. are incorrectly being reported as files in Linux remote mounts
## v2.0.6-release ## v2.0.6-release
<!-- markdownlint-disable-next-line -->
### Issues ### Issues
* \#42 [bug] Remote mount directory listing on Windows connected to Linux is failing * \#42 [bug] Remote mount directory listing on Windows connected to Linux is failing
* \#43 [bug] Directories are not importing properly for Sia * \#43 [bug] Directories are not importing properly for Sia
* \#44 [bug] Windows-to-Linux remote mount ignores `CREATE_NEW` * \#44 [bug] Windows-to-Linux remote mount ignores `CREATE_NEW`

View File

@@ -51,6 +51,10 @@ if(PROJECT_IS_ARM64)
add_definitions(-DPROJECT_IS_ARM64) add_definitions(-DPROJECT_IS_ARM64)
endif() endif()
if(PROJECT_IS_DARWIN)
add_definitions(-DPROJECT_IS_DARWIN)
endif()
if(PROJECT_IS_MINGW) if(PROJECT_IS_MINGW)
option(PROJECT_ENABLE_WIN32_LONG_PATH_NAMES "Enable path sizes of 32767 characters on Windows" OFF) option(PROJECT_ENABLE_WIN32_LONG_PATH_NAMES "Enable path sizes of 32767 characters on Windows" OFF)
if(PROJECT_ENABLE_WIN32_LONG_PATH_NAMES) if(PROJECT_ENABLE_WIN32_LONG_PATH_NAMES)
@@ -115,6 +119,16 @@ if(PROJECT_BUILD)
${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/version.cpp ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/version.cpp
@ONLY @ONLY
) )
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${PROJECT_NAME}.iss.in")
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${PROJECT_NAME}.iss.in
${PROJECT_DIST_DIR}/../${PROJECT_NAME}.iss
@ONLY
)
endif()
find_package(ICU REQUIRED COMPONENTS data i18n io uc)
else() else()
message(STATUS "-=[CMake Settings]=-") message(STATUS "-=[CMake Settings]=-")
message(STATUS " C standard: ${CMAKE_C_STANDARD}") message(STATUS " C standard: ${CMAKE_C_STANDARD}")
@@ -170,9 +184,12 @@ endif()
-DPROJECT_INTERFACE=1 -DPROJECT_INTERFACE=1
-DPROJECT_IS_ALPINE=${PROJECT_IS_ALPINE} -DPROJECT_IS_ALPINE=${PROJECT_IS_ALPINE}
-DPROJECT_IS_ARM64=${PROJECT_IS_ARM64} -DPROJECT_IS_ARM64=${PROJECT_IS_ARM64}
-DPROJECT_IS_DARWIN=${PROJECT_IS_DARWIN}
-DPROJECT_IS_MINGW=${PROJECT_IS_MINGW} -DPROJECT_IS_MINGW=${PROJECT_IS_MINGW}
-DPROJECT_IS_MINGW_UNIX=${PROJECT_IS_MINGW_UNIX} -DPROJECT_IS_MINGW_UNIX=${PROJECT_IS_MINGW_UNIX}
-DPROJECT_MAJOR_VERSION=${PROJECT_MAJOR_VERSION} -DPROJECT_MAJOR_VERSION=${PROJECT_MAJOR_VERSION}
-DPROJECT_MACOS_BUNDLE_ID=${PROJECT_MACOS_BUNDLE_ID}
-DPROJECT_MACOS_ICNS_NAME=${PROJECT_MACOS_ICNS_NAME}
-DPROJECT_MINOR_VERSION=${PROJECT_MINOR_VERSION} -DPROJECT_MINOR_VERSION=${PROJECT_MINOR_VERSION}
-DPROJECT_NAME=${PROJECT_NAME} -DPROJECT_NAME=${PROJECT_NAME}
-DPROJECT_RELEASE_ITER=${PROJECT_RELEASE_ITER} -DPROJECT_RELEASE_ITER=${PROJECT_RELEASE_ITER}

845
README.md
View File

@@ -1,153 +1,347 @@
# Repertory # Repertory
Repertory allows you to mount S3 and Sia via FUSE on Linux or via WinFSP Repertory allows you to mount **S3** and **Sia** storage as local drives using:
on Windows.
## Contents - **FUSE** (Linux/macOS)
- **WinFSP** (Windows)
1. [Details and Features](#details-and-features) It supports:
2. [Minimum Requirements](#minimum-requirements)
1. [Supported Operating Systems](#supported-operating-systems)
3. [GUI](#gui)
4. [Usage](#usage)
1. [Important Options](#important-options)
2. [Sia](#sia)
* [Sia Initial Configuration](#sia-initial-configuration)
* [Sia Mounting](#sia-mounting)
* [Sia Configuration File](#sia-configuration-file)
3. [S3](#s3)
* [S3 Initial Configuration](#s3-initial-configuration)
* [S3 Mounting](#s3-mounting)
* [S3 Configuration File](#s3-configuration-file)
5. [Data Directories](#data-directories)
1. [Linux Directories](#linux-directories)
2. [Windows Directories](#windows-directories)
6. [Remote Mounting](#remote-mounting)
1. [Server Setup](#server-setup)
* [Remote Mount Configuration File Section](#remote-mount-configuration-file-section)
2. [Client Setup](#client-setup)
* [Client Remote Mounting](#client-remote-mounting)
* [Remote Mount Configuration File](#remote-mount-configuration-file)
7. [Compiling](#compiling)
1. [Linux Compilation](#linux-compilation)
2. [Windows Setup](#windows-compilation)
8. [Credits](#credits)
9. [Developer Public Key](#developer-public-key)
10. [Consult the Wiki for additional information](https://git.fifthgrid.com/BlockStorage/repertory/wiki)
## Details and Features - Local mounts
- Remote encrypted mounts between systems
- Optional file name and data encryption using `XChaCha20-Poly1305` and `Argon2id` for key generation
* Optimized for [Plex Media Server](https://www.plex.tv/) ---
* Remote mounting of `repertory` instances on Linux and Windows
* Securely share your mounts over TCP/IP via `XChaCha20-Poly1305` with other systems on your network or over the internet.
* Cross-platform support (Linux 64-bit, Linux arm64/aarch64, Windows 64-bit)
* Optionally encrypt file names and file data via `XChaCha20-Poly1305` in S3 mounts
## Minimum Requirements ## 📖 Contents
* [Sia renterd](https://github.com/SiaFoundation/renterd/releases) v2.0.0+ for Sia support 1. [Quick Start (Sia Example)](#-quick-start-sia-example)
* Linux requires `fusermount3`; otherwise, `repertory` must be manually compiled with `libfuse2` support 2. [Details & Features](#-details-and-features)
* Windows requires the following dependencies to be installed: 3. [Minimum Requirements](#-minimum-requirements)
* [WinFSP 2025](https://github.com/winfsp/winfsp/releases/download/v2.1/winfsp-2.1.25156.msi) - [Supported Operating Systems](#supported-operating-systems)
4. [Data Directories](#-data-directories)
5. [GUI](#-gui)
6. [Usage](#-usage)
- [Important Options](#important-options)
- [Unmounting](#unmounting)
7. [Sia Setup](#-sia)
- [Sia Initial Configuration](#sia-initial-configuration)
- [Sia Mounting](#sia-mounting)
- [Sia Configuration File](#sia-configuration-file)
8. [S3 Setup](#-s3)
- [S3 Initial Configuration](#s3-initial-configuration)
- [S3 Mounting](#s3-mounting)
- [S3 Configuration File](#s3-configuration-file)
9. [Remote Mounting](#-remote-mounting)
- [Server Setup](#server-setup)
- [Client Setup](#client-setup)
- [Remote Mount Configuration File](#remote-mount-configuration-file)
10. [Compiling from Source](#-compiling)
- [Linux Compilation](#linux-compilation)
- [macOS Compilation](#macos-compilation)
- [Windows Compilation](#windows-compilation)
11. [Credits](#-credits)
12. [Developer Public Key](#-developer-public-key)
13. [Consult the Wiki for additional information](https://git.fifthgrid.com/BlockStorage/repertory/wiki)
---
## 🚀 Quick Start (Sia Example)
> 💡 Want to mount S3 instead?
> Skip ahead to [S3 Setup](#-s3) — the process is almost identical.
This example mounts a Sia bucket from a running [renterd](https://github.com/SiaFoundation/renterd) instance.
---
### 1. Install dependencies
#### Linux
``` shell
sudo apt install fuse3 # Debian/Ubuntu
# or
sudo dnf install fuse3 # Fedora
```
#### macOS
- Install [macFUSE 4.10.2](https://github.com/macfuse/macfuse/releases/download/macfuse-4.10.2/macfuse-4.10.2.dmg)
#### Windows
- Install [WinFSP 2025](https://github.com/winfsp/winfsp/releases/download/v2.1/winfsp-2.1.25156.msi)
---
### 2. Configure
Replace placeholders with your actual values:
``` shell
repertory --name mybucket -set HostConfig.ApiPassword "<renterd api password>"
repertory --name mybucket -set SiaConfig.Bucket "<bucket name>"
```
Optional:
``` shell
# If renterd is not running locally
repertory --name mybucket -set HostConfig.HostNameOrIp "<hostname or IP>"
# If renterd uses a non-default port (default 9980)
repertory --name mybucket -set HostConfig.ApiPort <port>
```
---
### 3. Mount
<!-- markdownlint-disable-next-line -->
#### Linux
``` shell
repertory --name mybucket /mnt/mybucket
```
<!-- markdownlint-disable-next-line -->
#### macOS
``` shell
repertory --name mybucket /Volumes/mybucket
```
<!-- markdownlint-disable-next-line -->
#### Windows
``` shell
repertory --name mybucket t:
```
---
### 4. Unmount
``` shell
repertory --name mybucket --unmount
```
---
## ✨ Details and Features
- **Optimized for [Plex Media Server](https://www.plex.tv/).**
- Remote mounting of `repertory` instances between Linux, macOS, and/or Windows.
- Securely share your mounts over TCP/IP via `XChaCha20-Poly1305` with other systems on your network or over the internet.
- Cross-platform support (Linux, macOS, and Windows).
- Optionally encrypt file names and file data via `XChaCha20-Poly1305` in S3 mounts.
---
## 📋 Minimum Requirements
- **Sia:** [renterd](https://github.com/SiaFoundation/renterd/releases) v2.0.0+ for Sia support
- **Linux:** requires `fusermount3`; otherwise, `repertory` must be manually compiled with `libfuse2` support
- **macOS:** requires:
- [macFUSE 4.10.2](https://github.com/macfuse/macfuse/releases/download/macfuse-4.10.2/macfuse-4.10.2.dmg)
- **Windows:** requires:
- [WinFSP 2025](https://github.com/winfsp/winfsp/releases/download/v2.1/winfsp-2.1.25156.msi)
### Supported Operating Systems ### Supported Operating Systems
Only 64-bit operating systems are supported Only **64-bit operating systems** are supported:
* Linux `arm64/aarch64` - Linux `arm64/aarch64`
* Linux `amd64` - Linux `x86_64`
* Windows 64-bit 10, 11 - macOS `arm64/aarch64`
- macOS `x86_64`
- Windows `x86_64` 10, 11
## GUI ---
As of `v2.0.5-rc`, mounts can be managed using the `Repertory Management Portal`. ## 📂 Data Directories
To launch the portal, execute the following command:
* `repertory -ui` <!-- markdownlint-disable-next-line -->
* The default username is `repertory` ### Linux
* The default password is `repertory`
After first launch, `ui.json` will be created in the appropriate data directory. ``` shell
See [Data Directories](#data-directories). ~/.local/repertory2/s3
You should modify this file directly or use the portal to change the default ~/.local/repertory2/sia
username and password. ```
### Screenshot <!-- markdownlint-disable-next-line -->
### Windows
<a href="https://ibb.co/fVyJqnbF"><img src="https://i.ibb.co/fVyJqnbF/repertory-portal.png" alt="repertory-portal" border="0"></a> ``` shell
%LOCALAPPDATA%\repertory2\s3
%LOCALAPPDATA%\repertory2\sia
```
## Usage **IMPORTANT:**
It is highly recommended to **exclude** these folders from any anti-virus/anti-malware applications as severe performance issues may arise. Excluding the mounted drive letter is also highly recommended.
---
## 🖥 GUI
As of `v2.0.6-release`, mounts can be managed using the **Repertory Management Portal**.
Launch the portal:
``` shell
repertory -ui
```
### ⚠️ Security tip
- Change the default UI credentials on first launch (`ui.json`) or via the portal
- Default username: `repertory`
- Default password: `repertory`
After first launch, `ui.json` will be created in the appropriate data directory (see [Data Directories](#-data-directories)). Modify this file directly or use the portal to change the default credentials.
### Screenshots
#### Login screen
![alt text](assets/login.png)
#### Home screen
![alt text](assets/home.png)
---
## 🛠 Usage
### Important Options ### Important Options
* `--help` - `--help`
* Display all mount utility options Display all mount utility options.
* `-f` - `-f`
* Keep process in foreground on Linux. Keep process in foreground on Linux.
* `--name, -na [name]` - `--name, -na [name]`
* Identifies a unique configuration name to support multiple mounts. Identifies a unique configuration name to support multiple mounts.
* The `--name` option can be set to any valid value allowed as a file name for your filesystem. The `--name` option can be set to any valid value allowed as a file name for your filesystem.
* For Sia, the bucket name will be set to the same value if it is empty in the configuration file. **The `--name` option is required.**
* If the `--name` option is not specified, `default` will be used.
* For S3, the `--name` option is required and does not affect the bucket name.
* `-dc` - `-dc`
* Display mount configuration Display mount configuration.
* For Sia, `--name` is optional For Sia, the `--name` option is required.
* For S3, the `-s3` option is required along with `--name` For S3, the `-s3` and `--name` options are required.
### Sia ### Unmounting
#### Sia Initial Configuration #### Remote
* Required steps: ``` shell
* Set the appropriate bucket name and `renterd` API password in `repertory` configuration: repertory -rm 192.168.0.1:20000 --unmount
* To use `default` as the bucket name and configuration name, you only need to set the `renterd` API password: ```
* `repertory -set HostConfig.ApiPassword '<my password>'`
* To specify a different bucket name while using `default` as the configuration name:
* `repertory -set HostConfig.ApiPassword '<my password>'`
* `repertory -set SiaConfig.Bucket '<my bucket>'`
* For all other configurations:
* `repertory --name '<my config name>' -set HostConfig.ApiPassword '<my password>'`
* `repertory --name '<my config name>' -set SiaConfig.Bucket '<my bucket name>'`
* Optional steps: #### S3
* Set a user name used during `renterd` basic authentication:
* `repertory -set HostConfig.ApiUser '<my user>'`
* `repertory --name '<my config name>' -set HostConfig.ApiUser '<my user>'`
* Set a custom agent string (default `Sia-Agent`):
* `repertory -set HostConfig.AgentString '<my agent>'`
* `repertory --name '<my config name>' -set HostConfig.AgentString '<my agent>'`
* Set the host name or IP of the `renterd` instance (default `localhost`):
* `repertory -set HostConfig.HostNameOrIp '<my host name>'`
* `repertory --name '<my config name>' -set HostConfig.HostNameOrIp '<my host name>'`
* Set the `renterd` API port (default `9980`):
* `repertory -set HostConfig.ApiPort 9981`
* `repertory --name '<my config name>' -set HostConfig.ApiPort 9981`
* To verify/view all configuration options: ``` shell
* `repertory -dc` repertory -s3 --name '<my config name>' --unmount
* `repertory --name '<my config name>' -dc` ```
* Example:
* `repertory --name default -dc`
#### Sia Mounting #### Sia
* Linux: ``` shell
* `repertory /mnt/location` repertory --name '<my config name>' --unmount
* `repertory --name '<my config name>' /mnt/location` ```
* Example:
* `repertory --name default /mnt/location`
* Windows: ---
* `repertory t:`
* `repertory --name '<my config name>' t:`
* Example:
* `repertory --name default t:`
#### Sia Configuration File ## 🔒 Security Best Practices
When enabling **encryption tokens** for S3 or remote mounts:
- Use a **long, random string**.
- Store it **offline** (password manager and an offline backup).
- Losing it means **permanent data loss**.
---
## ☁️ Sia
### Sia Initial Configuration
**Required steps:**
- Set the appropriate bucket name and `renterd` API password in `repertory` configuration:
``` shell
repertory --name '<my config name>' -set HostConfig.ApiPassword '<my password>'
repertory --name '<my config name>' -set SiaConfig.Bucket '<my bucket name>'
```
**Optional steps:**
- Set a user name used during `renterd` basic authentication:
``` shell
repertory --name '<my config name>' -set HostConfig.ApiUser '<my user>'
```
- Set a custom agent string (default `Sia-Agent`):
``` shell
repertory --name '<my config name>' -set HostConfig.AgentString '<my agent>'
```
- Set the host name or IP of the `renterd` instance (default `localhost`):
``` shell
repertory --name '<my config name>' -set HostConfig.HostNameOrIp '<my host name>'
```
- Set the `renterd` API port (default `9980`):
``` shell
repertory --name '<my config name>' -set HostConfig.ApiPort 9981
```
**Verify/view all configuration options:**
``` shell
repertory --name '<my config name>' -dc
# Example:
repertory --name my_bucket -dc
```
### Sia Mounting
<!-- markdownlint-disable-next-line -->
#### Linux
``` shell
repertory --name '<my config name>' /mnt/location
# Example:
repertory --name my_bucket /mnt/location
```
<!-- markdownlint-disable-next-line -->
#### macOS
``` shell
repertory --name '<my config name>' /Volumes/mybucket
# Example:
repertory --name my_bucket /Volumes/mybucket
```
<!-- markdownlint-disable-next-line -->
#### Windows
``` shell
repertory --name '<my config name>' t:
# Example:
repertory --name my_bucket t:
```
### Sia Configuration File
```json ```json
{ {
@@ -187,55 +381,105 @@ username and password.
"RetryReadCount": 6, "RetryReadCount": 6,
"RingBufferFileSize": 512, "RingBufferFileSize": 512,
"SiaConfig": { "SiaConfig": {
"Bucket": "default" "Bucket": "my_bucket"
}, },
"TaskWaitMs": 100, "TaskWaitMs": 100,
"Version": 1 "Version": 1
} }
``` ```
### S3 ---
#### S3 Initial Configuration ## 🪣 S3
* Required steps: ### S3 Initial Configuration
* Set the appropriate base URL:
* `repertory -s3 --name '<my config name>' -set S3Config.URL '<my url>'`
* Example:
* `repertory -s3 --name minio -set S3Config.URL 'http://localhost:9000'`
* Set the appropriate bucket name:
* `repertory -s3 --name '<my config name>' -set S3Config.Bucket '<my bucket name>'`
* Set the appropriate access key:
* `repertory -s3 --name '<my config name>' -set S3Config.AccessKey '<my access key>'`
* Set the appropriate secret key:
* `repertory -s3 --name '<my config name>' -set S3Config.SecretKey '<my secret key>'`
* For Sia and most local S3 gateway instances, enable path style URL's:
* `repertory -s3 --name '<my config name>' -set S3Config.UsePathStyle true`
* Optional steps: **Required steps:**
* Set an appropriate region. Default is set to `any`:
* `repertory -s3 --name '<my config name>' -set S3Config.Region '<my region>'`
* Enable encrypted file names and file data. Set a strong, random encryption token and be sure to store it in a secure backup location:
* `repertory -s3 --name '<my config name>' -set S3Config.EncryptionToken '<my strong password>'`
* To verify/view all configuration options: - Set the appropriate base URL:
* `repertory -s3 --name '<my config name>' -dc`
* Example:
* `repertory -s3 --name minio -dc`
#### S3 Mounting ``` shell
repertory -s3 --name '<my config name>' -set S3Config.URL '<my url>'
# Example:
repertory -s3 --name minio -set S3Config.URL 'http://localhost:9000'
```
* Linux: - Set the appropriate bucket name:
* `repertory -s3 --name '<my config name>' /mnt/location`
* Example:
* `repertory -s3 --name minio /mnt/location`
* Windows: ``` shell
* `repertory -s3 --name '<my config name>' t:` repertory -s3 --name '<my config name>' -set S3Config.Bucket '<my bucket name>'
* Example: ```
* `repertory -s3 --name minio t:`
#### S3 Configuration File - Set the appropriate access key:
``` shell
repertory -s3 --name '<my config name>' -set S3Config.AccessKey '<my access key>'
```
- Set the appropriate secret key:
``` shell
repertory -s3 --name '<my config name>' -set S3Config.SecretKey '<my secret key>'
```
- For Sia and most local S3 gateway instances, enable path style URLs:
``` shell
repertory -s3 --name '<my config name>' -set S3Config.UsePathStyle true
```
**Optional steps:**
- Set an appropriate region. Default is `any`:
``` shell
repertory -s3 --name '<my config name>' -set S3Config.Region '<my region>'
```
- Enable encrypted file names and file data. Set a strong, random encryption token and store it securely:
``` shell
repertory -s3 --name '<my config name>' -set S3Config.EncryptionToken '<my strong password>'
```
**Verify/view all configuration options:**
``` shell
repertory -s3 --name '<my config name>' -dc
# Example:
repertory -s3 --name minio -dc
```
### S3 Mounting
<!-- markdownlint-disable-next-line -->
#### Linux
``` shell
repertory -s3 --name '<my config name>' /mnt/location
# Example:
repertory -s3 --name minio /mnt/location
```
<!-- markdownlint-disable-next-line -->
#### macOS
``` shell
repertory -s3 --name '<my config name>' /Volumes/minio
# Example:
repertory -s3 --name minio /Volumes/minio
```
<!-- markdownlint-disable-next-line -->
#### Windows
``` shell
repertory -s3 --name '<my config name>' t:
# Example:
repertory -s3 --name minio t:
```
### S3 Configuration File
```json ```json
{ {
@@ -280,100 +524,128 @@ username and password.
} }
``` ```
### Data Directories ---
#### Linux Directories ## 🌐 Remote Mounting
* `~/.local/repertory2/s3` `repertory` allows local mounts to be shared with other computers on your network or over the internet. This option is referred to as **remote mounting**.
* `~/.local/repertory2/sia`
#### Windows Directories
* `%LOCALAPPDATA%\repertory2\s3`
* `%LOCALAPPDATA%\repertory2\sia`
* Examples:
* `C:\Users\Tom\AppData\Local\repertory2\s3`
* `C:\Users\Tom\AppData\Local\repertory2\sia`
* IMPORTANT:
* It is highly recommended to exclude this folder from any anti-virus/anti-malware applications as severe performance issues may arise.
* Excluding the mounted drive letter is also highly recommended.
## Remote Mounting
`repertory` allows local mounts to be shared with other computers on your network
or over the internet. This option is referred to as remote mounting.
### Server Setup ### Server Setup
The following steps must be performed on the mount you wish to share with The following steps must be performed on the mount you wish to share with other systems. Changes to configuration will not take effect while a mount is active, so it is recommended to unmount beforehand.
other systems. Changes to configuration will not take affect while a mount is
active, so it is recommended to unmount beforehand.
* Required steps: **Required steps:**
* Enable remote mount:
* Sia
* `repertory -set RemoteMount.Enable true`
* `repertory --name '<my config name>' -set RemoteMount.Enable true`
* S3:
* `repertory -s3 --name '<my config name>' -set RemoteMount.Enable true`
* Set a secure encryption token:
* Sia:
* `repertory -set RemoteMount.EncryptionToken '<my secure password>'`
* `repertory --name '<my config name>' -set RemoteMount.EncryptionToken '<my secure password>'`
* S3:
* `repertory -s3 --name '<my config name>' -set RemoteMount.EncryptionToken '<my secure password>'`
* Optional steps: - Enable remote mount:
* Change the port clients will use to connect to your mount:
* Sia:
* `repertory -set RemoteMount.ApiPort 20000`
* `repertory --name '<my config name>' -set RemoteMount.ApiPort 20000`
* S3:
* `repertory -s3 --name '<my config name>' -set RemoteMount.ApiPort 20000`
* IMPORTANT: - **Sia**
* Be sure to configure your firewall to allow incoming TCP connections on the port configured in `RemoteMount.ApiPort`.
``` shell
repertory -set RemoteMount.Enable true
repertory --name '<my config name>' -set RemoteMount.Enable true
```
- **S3**
``` shell
repertory -set RemoteMount.Enable true
repertory -s3 --name '<my config name>' -set RemoteMount.Enable true
```
- Set a secure encryption token:
- **Sia**
``` shell
repertory -set RemoteMount.EncryptionToken '<my secure password>'
repertory --name '<my config name>' -set RemoteMount.EncryptionToken '<my secure password>'
```
- **S3**
``` shell
repertory -s3 --name '<my config name>' -set RemoteMount.EncryptionToken '<my secure password>'
```
**Optional steps:**
- Change the port clients will use to connect to your mount:
- **Sia**
``` shell
repertory -set RemoteMount.ApiPort 20000
repertory --name '<my config name>' -set RemoteMount.ApiPort 20000
```
- **S3**
``` shell
repertory -s3 --name '<my config name>' -set RemoteMount.ApiPort 20000
```
**IMPORTANT:**
Be sure to configure your firewall to allow incoming TCP connections on the port configured in `RemoteMount.ApiPort`.
#### Remote Mount Configuration File Section #### Remote Mount Configuration File Section
```json ```json
{ {
...
"RemoteMount": { "RemoteMount": {
"ApiPort": 20000, "ApiPort": 20000,
"ClientPoolSize": 20, "ClientPoolSize": 20,
"Enable": true, "Enable": true,
"EncryptionToken": "<my secure password>" "EncryptionToken": "<my secure password>"
}, }
...
} }
``` ```
### Client Setup ### Client Setup
Client configuration is provider agnostic, so there's no need to specify `-s3` Client configuration is provider agnostic, so there's no need to specify `-s3` for S3 providers.
for S3 providers.
* Required steps: **Required steps:**
* Set the encryption token to the same value configured during server setup:
* `repertory -rm <host name or IP>:<port> -set RemoteConfig.EncryptionToken '<my secure password>'` - Set the encryption token to the same value configured during server setup:
* Replace `<host name or IP>` with the host name or IP of the server
* Replace `<port>` with the value of `RemoteMount.ApiPort` used in the server configuration ``` shell
* Example: repertory -rm <host name or IP>:<port> -set RemoteConfig.EncryptionToken '<my secure password>'
* `repertory -rm 192.168.1.10:20000 -set RemoteConfig.EncryptionToken '<my secure password>'` # Replace <host name or IP> with the host name or IP of the server
* `repertory -rm my.host.com:20000 -set RemoteConfig.EncryptionToken '<my secure password>'` # Replace <port> with the value of RemoteMount.ApiPort used in the server configuration
# Example:
repertory -rm 192.168.1.10:20000 -set RemoteConfig.EncryptionToken '<my secure password>'
repertory -rm my.host.com:20000 -set RemoteConfig.EncryptionToken '<my secure password>'
```
#### Client Remote Mounting #### Client Remote Mounting
* Linux: <!-- markdownlint-disable-next-line -->
* `repertory -rm <host name or IP>:<port> /mnt/location` ##### Linux
* Example:
* `repertory -rm 192.168.1.10:20000 /mnt/location`
* Windows: ``` shell
* `repertory -rm <host name or IP>:<port> t:` repertory -rm <host name or IP>:<port> /mnt/location
* Example: # Example:
* `repertory -rm 192.168.1.10:20000 t:` repertory -rm 192.168.1.10:20000 /mnt/location
```
<!-- markdownlint-disable-next-line -->
##### macOS
``` shell
repertory -rm <host name or IP>:<port> /Volumes/remotemount
# Example:
repertory -rm 192.168.1.10:20000 /Volumes/remotemount
```
<!-- markdownlint-disable-next-line -->
##### Windows
``` shell
repertory -rm <host name or IP>:<port> t:
# Example:
repertory -rm 192.168.1.10:20000 t:
```
#### Remote Mount Configuration File #### Remote Mount Configuration File
@@ -397,67 +669,108 @@ for S3 providers.
} }
``` ```
## Compiling ---
Successful compilation will result in all files required for execution to be placed ## 🧰 Compiling
in the `dist/` directory
Successful compilation will place all required files for execution in the `dist/` directory.
### Linux Compilation ### Linux Compilation
* Ensure `docker` is installed - Ensure `docker` is installed
* For x86_64:
* RelWithDebInfo: `scripts/make_unix.sh`
* Release: `scripts/make_unix.sh x86_64 Release`
* Debug: `scripts/make_unix.sh x86_64 Debug`
* For aarch64: - For `x86_64`:
* RelWithDebInfo: `scripts/make_unix.sh aarch64`
* Release: `scripts/make_unix.sh aarch64 Release` ``` shell
* Debug: `scripts/make_unix.sh aarch64 Debug` scripts/make_unix.sh x86_64
scripts/make_unix.sh x86_64 Release
scripts/make_unix.sh x86_64 Debug
```
- For `aarch64`:
``` shell
scripts/make_unix.sh aarch64
scripts/make_unix.sh aarch64 Release
scripts/make_unix.sh aarch64 Debug
```
### macOS Compilation
- Ensure `Xcode` and `CMake` are installed
- For `x86_64`:
``` shell
scripts/make_unix.sh x86_64
scripts/make_unix.sh x86_64 Release
scripts/make_unix.sh x86_64 Debug
```
- For `aarch64`:
``` shell
scripts/make_unix.sh aarch64
scripts/make_unix.sh aarch64 Release
scripts/make_unix.sh aarch64 Debug
```
### Windows Compilation ### Windows Compilation
* OFFICIAL: Cross-compiling on Linux - **OFFICIAL: Cross-compiling on Linux**
* Ensure `docker` is installed
* RelWithDebInfo: `scripts/make_win32.sh`
* Release: `scripts/make_win32.sh x86_64 Release`
* Debug: `scripts/make_win32.sh x86_64 Debug`
* UNOFFICIAL: Compiling on Windows - Ensure `docker` is installed
* Ensure latest [MSYS2](https://www.msys2.org/) is installed
* RelWithDebInfo: `scripts\make_win32.cmd`
* Release: `scripts\make_win32.cmd x86_64 Release`
* Debug: `scripts\make_win32.cmd x86_64 Debug`
## Credits ``` shell
scripts/make_win32.sh x86_64
scripts/make_win32.sh x86_64 Release
scripts/make_win32.sh x86_64 Debug
```
* [binutils](https://www.gnu.org/software/binutils/) - **UNOFFICIAL: Compiling on Windows**
* [boost c++ libraries](https://www.boost.org/)
* [cpp-httplib](https://github.com/yhirose/cpp-httplib)
* [curl](https://curl.haxx.se/)
* [docker](https://www.docker.com/)
* [Google Test](https://github.com/google/googletest)
* [ICU](https://icu.unicode.org/)
* [JSON for Modern C++](https://github.com/nlohmann/json)
* [libexpat](https://github.com/libexpat/libexpat)
* [libfuse](https://github.com/libfuse/libfuse)
* [libsodium](https://doc.libsodium.org/)
* [mingw-w64](https://www.mingw-w64.org/)
* [MSYS2](https://www.msys2.org)
* [OpenSSL](https://www.openssl.org/)
* [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/)
* [pugixml](https://pugixml.org/)
* [RocksDB](https://rocksdb.org)
* [ScPrime](https://scpri.me/)
* [Sia Decentralized Cloud Storage](https://sia.tech/)
* [spdlog](https://github.com/gabime/spdlog)
* [SQLite](https://www.sqlite.org)
* [stduuid](https://github.com/mariusbancila/stduuid)
* [Storj](https://storj.io/)
* [WinFSP - FUSE for Windows](https://github.com/billziss-gh/winfsp)
* [zlib](https://zlib.net/)
## Developer Public Key - Ensure latest [MSYS2](https://www.msys2.org/) is installed
``` shell
scripts\make_win32.cmd x86_64
scripts\make_win32.cmd x86_64 Release
scripts\make_win32.cmd x86_64 Debug
```
---
## 📜 Credits
- [binutils](https://www.gnu.org/software/binutils/)
- [boost c++ libraries](https://www.boost.org/)
- [cpp-httplib](https://github.com/yhirose/cpp-httplib)
- [curl](https://curl.haxx.se/)
- [docker](https://www.docker.com/)
- [Google Test](https://github.com/google/googletest)
- [ICU](https://icu.unicode.org/)
- [JSON for Modern C++](https://github.com/nlohmann/json)
- [libexpat](https://github.com/libexpat/libexpat)
- [libfuse](https://github.com/libfuse/libfuse)
- [libsodium](https://doc.libsodium.org/)
- [macFUSE](https://macfuse.github.io/)
- [mingw-w64](https://www.mingw-w64.org/)
- [MSYS2](https://www.msys2.org)
- [OpenSSL](https://www.openssl.org/)
- [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/)
- [pugixml](https://pugixml.org/)
- [RocksDB](https://rocksdb.org)
- [ScPrime](https://scpri.me/)
- [Sia Decentralized Cloud Storage](https://sia.tech/)
- [spdlog](https://github.com/gabime/spdlog)
- [SQLite](https://www.sqlite.org)
- [stduuid](https://github.com/mariusbancila/stduuid)
- [Storj](https://www.storj.io/)
- [WinFSP - FUSE for Windows](https://github.com/billziss-gh/winfsp)
- [zlib](https://zlib.net/)
---
## 🔑 Developer Public Key
```text ```text
-----BEGIN PUBLIC KEY----- -----BEGIN PUBLIC KEY-----

BIN
assets/blue/icon_24X24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

BIN
assets/blue/icon_40x40.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 B

BIN
assets/blue/icon_48x48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 B

BIN
assets/blue/logo.icns Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 820 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 820 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
assets/green/icon_24X24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
assets/green/icon_40x40.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
assets/green/icon_48x48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
assets/green/logo.icns Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

BIN
assets/home.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

BIN
assets/icon.icns Normal file

Binary file not shown.

BIN
assets/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 KiB

BIN
assets/login.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 KiB

BIN
assets/logo_blue.xcf Normal file

Binary file not shown.

BIN
assets/logo_green.xcf Normal file

Binary file not shown.

View File

@@ -35,13 +35,9 @@ list(APPEND PROJECT_CXXFLAGS_LIST
-Wcast-align -Wcast-align
-Wconversion -Wconversion
-Wdouble-promotion -Wdouble-promotion
-Wduplicated-branches
-Wduplicated-cond
-Wextra -Wextra
-Wformat=2 -Wformat=2
-Wlogical-op
-Wmisleading-indentation -Wmisleading-indentation
-Wno-useless-cast
-Wnon-virtual-dtor -Wnon-virtual-dtor
-Wnull-dereference -Wnull-dereference
-Wold-style-cast -Wold-style-cast
@@ -52,6 +48,15 @@ list(APPEND PROJECT_CXXFLAGS_LIST
-Wunused -Wunused
) )
if (NOT PROJECT_IS_DARWIN)
list(APPEND PROJECT_CXXFLAGS_LIST
-Wduplicated-branches
-Wduplicated-cond
-Wlogical-op
-Wno-useless-cast
)
endif()
list(APPEND PROJECT_CFLAGS_LIST list(APPEND PROJECT_CFLAGS_LIST
${PROJECT_COMMON_FLAG_LIST} ${PROJECT_COMMON_FLAG_LIST}
-std=c${CMAKE_C_STANDARD} -std=c${CMAKE_C_STANDARD}
@@ -62,7 +67,7 @@ list(APPEND PROJECT_CXXFLAGS_LIST
-std=gnu++${CMAKE_CXX_STANDARD} -std=gnu++${CMAKE_CXX_STANDARD}
) )
if(PROJECT_STATIC_LINK) if(NOT PROJECT_IS_DARWIN AND PROJECT_STATIC_LINK)
list(APPEND PROJECT_CMAKE_EXE_LINKER_FLAGS list(APPEND PROJECT_CMAKE_EXE_LINKER_FLAGS
-static-libgcc -static-libgcc
-static-libstdc++ -static-libstdc++
@@ -89,7 +94,11 @@ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${PROJECT_RELEASE_FLAG_L
set(CMAKE_EXE_LINKER_FLAGS "${PROJECT_CMAKE_EXE_LINKER_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "${PROJECT_CMAKE_EXE_LINKER_FLAGS}")
set(EXTERNAL_CMAKE_CXX_FLAGS "-include cstdint -include utility -fext-numeric-literals ${PROJECT_COMMON_FLAG_LIST}") set(EXTERNAL_CMAKE_CXX_FLAGS "-include cstdint -include utility ${PROJECT_COMMON_FLAG_LIST}")
if (NOT PROJECT_IS_DARWIN)
set(EXTERNAL_CMAKE_CXX_FLAGS "-fext-numeric-literals ${EXTERNAL_CMAKE_CXX_FLAGS}")
endif()
list(APPEND PROJECT_EXTERNAL_CMAKE_FLAGS list(APPEND PROJECT_EXTERNAL_CMAKE_FLAGS
-DCMAKE_BUILD_TYPE=${PROJECT_CMAKE_BUILD_TYPE} -DCMAKE_BUILD_TYPE=${PROJECT_CMAKE_BUILD_TYPE}
-DCMAKE_COLOR_MAKEFILE=${CMAKE_COLOR_MAKEFILE} -DCMAKE_COLOR_MAKEFILE=${CMAKE_COLOR_MAKEFILE}

View File

@@ -1,3 +1,7 @@
if (PROJECT_MACOS_ICNS_NAME)
set(PROJECT_MACOS_ICNS_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/assets/${PROJECT_MACOS_ICNS_NAME}")
endif()
function(set_common_target_options name) function(set_common_target_options name)
target_compile_definitions(${name} PUBLIC target_compile_definitions(${name} PUBLIC
${PROJECT_DEFINITIONS} ${PROJECT_DEFINITIONS}
@@ -12,6 +16,17 @@ function(set_common_target_options name)
${PROJECT_EXTERNAL_BUILD_ROOT}/lib ${PROJECT_EXTERNAL_BUILD_ROOT}/lib
) )
if (PROJECT_STATIC_LINK)
target_compile_definitions(${name} PRIVATE U_STATIC_IMPLEMENTATION)
endif()
target_link_libraries(${name} PRIVATE
ICU::io
ICU::i18n
ICU::uc
ICU::data
)
target_include_directories(${name} AFTER PUBLIC target_include_directories(${name} AFTER PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/include ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/include
${name}_INCLUDES ${name}_INCLUDES
@@ -31,11 +46,31 @@ function(add_project_executable2 name dependencies libraries headers sources is_
list(APPEND sources ${PROJECT_WINDOWS_VERSION_RC}) list(APPEND sources ${PROJECT_WINDOWS_VERSION_RC})
endif() endif()
if (PROJECT_IS_DARWIN AND PROJECT_MACOS_ICNS_SOURCE AND "${name}" STREQUAL "${PROJECT_NAME}")
set_source_files_properties(${PROJECT_MACOS_ICNS_SOURCE} PROPERTIES
MACOSX_PACKAGE_LOCATION "Resources"
)
add_executable(${name}
MACOSX_BUNDLE
${headers}
${sources}
${PROJECT_MACOS_ICNS_SOURCE}
${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/main.cpp
)
set_target_properties(${name} PROPERTIES
MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_ICON_FILE "${PROJECT_MACOS_ICNS_NAME}"
RESOURCE "${PROJECT_MACOS_ICNS_SOURCE}"
)
else()
add_executable(${name} add_executable(${name}
${headers} ${headers}
${sources} ${sources}
${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/main.cpp ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/${name}/main.cpp
) )
endif()
foreach(dependency ${dependencies}) foreach(dependency ${dependencies})
set_common_target_options(${dependency}) set_common_target_options(${dependency})

View File

@@ -1,20 +1,22 @@
set(BINUTILS_HASH ce2017e059d63e67ddb9240e9d4ec49c2893605035cd60e92ad53177f4377237) set(BINUTILS_HASH ce2017e059d63e67ddb9240e9d4ec49c2893605035cd60e92ad53177f4377237)
set(BOOST2_HASH 7bd7ddceec1a1dfdcbdb3e609b60d01739c38390a5f956385a12f3122049f0ca) set(BOOST2_HASH 7bd7ddceec1a1dfdcbdb3e609b60d01739c38390a5f956385a12f3122049f0ca)
set(BOOST_HASH 3621533e820dcab1e8012afd583c0c73cf0f77694952b81352bf38c1488f9cb4) set(BOOST_HASH 9de758db755e8330a01d995b0a24d09798048400ac25c03fc5ea9be364b13c93)
set(CPP_HTTPLIB_HASH 410a1347ed6bcbcc4a19af8ed8ad3873fe9fa97731d52db845c4c78f3f9c31e6) set(CPP_HTTPLIB_HASH a66f908f50ccb119769adce44fe1eac75f81b6ffab7c4ac0211bb663ffeb2688)
set(CURL_HASH 2937cadde007aa3a52a17c21ac9153ea054700f37926d1d96602bf07e888c847) set(CURL_HASH d4d9a5001b491f5726efe9b50bc4aad03029506e73c9261272e809c64b05e814)
set(EXPAT_HASH 85372797ff0673a8fc4a6be16466bb5a0ca28c0dcf3c6f7ac1686b4a3ba2aabb) set(EXPAT_HASH 85372797ff0673a8fc4a6be16466bb5a0ca28c0dcf3c6f7ac1686b4a3ba2aabb)
set(GCC_HASH 51b9919ea69c980d7a381db95d4be27edf73b21254eb13d752a08003b4d013b1) set(GCC_HASH 7294d65cc1a0558cb815af0ca8c7763d86f7a31199794ede3f630c0d1b0a5723)
set(GTEST_HASH 65fab701d9829d38cb77c14acdc431d2108bfdbf8979e40eb8ae567edf10b27c) set(GTEST_HASH 65fab701d9829d38cb77c14acdc431d2108bfdbf8979e40eb8ae567edf10b27c)
set(ICU_HASH a2c443404f00098e9e90acf29dc318e049d2dc78d9ae5f46efb261934a730ce2) set(ICU_HASH a2c443404f00098e9e90acf29dc318e049d2dc78d9ae5f46efb261934a730ce2)
set(INNOSETUP_HASH fa73bf47a4da250d185d07561c2bfda387e5e20db77e4570004cf6a133cc10b1)
set(JSON_HASH 4b92eb0c06d10683f7447ce9406cb97cd4b453be18d7279320f7b2f025c10187) set(JSON_HASH 4b92eb0c06d10683f7447ce9406cb97cd4b453be18d7279320f7b2f025c10187)
set(LIBSODIUM_HASH 8e5aeca07a723a27bbecc3beef14b0068d37e7fc0e97f51b3f1c82d2a58005c1) set(LIBSODIUM_HASH 8e5aeca07a723a27bbecc3beef14b0068d37e7fc0e97f51b3f1c82d2a58005c1)
set(MINGW_HASH 5afe822af5c4edbf67daaf45eec61d538f49eef6b19524de64897c6b95828caf) set(MINGW_HASH 5afe822af5c4edbf67daaf45eec61d538f49eef6b19524de64897c6b95828caf)
set(OPENSSL_HASH 529043b15cffa5f36077a4d0af83f3de399807181d607441d734196d889b641f) set(OPENSSL_HASH b6a5f44b7eb69e3fa35dbf15524405b44837a481d43d81daddde3ff21fcbb8e9)
set(PKG_CONFIG_HASH 6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591) set(PKG_CONFIG_HASH 6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591)
set(PUGIXML_HASH 655ade57fa703fb421c2eb9a0113b5064bddb145d415dd1f88c79353d90d511a) set(PUGIXML_HASH 655ade57fa703fb421c2eb9a0113b5064bddb145d415dd1f88c79353d90d511a)
set(ROCKSDB_HASH afccfab496556904900afacf7d99887f1d50cb893e5d2288bd502db233adacac) set(ROCKSDB_HASH 7ec942baab802b2845188d02bc5d4e42c29236e61bcbc08f5b3a6bdd92290c22)
set(SPDLOG_HASH 15a04e69c222eb6c01094b5c7ff8a249b36bb22788d72519646fb85feb267e67) set(SPDLOG_HASH 15a04e69c222eb6c01094b5c7ff8a249b36bb22788d72519646fb85feb267e67)
set(SQLITE_HASH 9ad6d16cbc1df7cd55c8b55127c82a9bca5e9f287818de6dc87e04e73599d754) set(SQLITE_HASH 1d3049dd0f830a025a53105fc79fd2ab9431aea99e137809d064d8ee8356b032)
set(STDUUID_HASH b1176597e789531c38481acbbed2a6894ad419aab0979c10410d59eb0ebf40d3) set(STDUUID_HASH b1176597e789531c38481acbbed2a6894ad419aab0979c10410d59eb0ebf40d3)
set(WINFSP_HASH 073a70e00f77423e34bed98b86e600def93393ba5822204fac57a29324db9f7a)
set(ZLIB_HASH 17e88863f3600672ab49182f217281b6fc4d3c762bde361935e436a95214d05c) set(ZLIB_HASH 17e88863f3600672ab49182f217281b6fc4d3c762bde361935e436a95214d05c)

View File

@@ -4,13 +4,17 @@ set(Boost_USE_STATIC_LIBS ${PROJECT_STATIC_LINK})
set(CURL_USE_STATIC_LIBS ${PROJECT_STATIC_LINK}) set(CURL_USE_STATIC_LIBS ${PROJECT_STATIC_LINK})
set(OPENSSL_USE_STATIC_LIBS ${PROJECT_STATIC_LINK}) set(OPENSSL_USE_STATIC_LIBS ${PROJECT_STATIC_LINK})
set(SFML_STATIC_LIBRARIES ${PROJECT_STATIC_LINK}) set(SFML_STATIC_LIBRARIES ${PROJECT_STATIC_LINK})
set(ZLIB_USE_STATIC_LIBS ${PROJECT_STATIC_LINK}) if (PROJECT_IS_DARWIN)
set(ZLIB_USE_STATIC_LIBS OFF)
else()
set(ZLIB_USE_STATIC_LIBS ${PROJECT_STATIC_LINK})
endif()
set(wxWidgets_USE_STATIC ${PROJECT_STATIC_LINK}) set(wxWidgets_USE_STATIC ${PROJECT_STATIC_LINK})
set(ICU_USE_STATIC_LIBS ${PROJECT_STATIC_LINK})
include(cmake/libraries/icu.cmake)
include(cmake/libraries/openssl.cmake) include(cmake/libraries/openssl.cmake)
include(cmake/libraries/boost.cmake) include(cmake/libraries/boost.cmake)
include(cmake/libraries/cpp_httplib.cmake) include(cmake/libraries/cpp_httplib.cmake)
include(cmake/libraries/curl.cmake) include(cmake/libraries/curl.cmake)
include(cmake/libraries/fuse.cmake) include(cmake/libraries/fuse.cmake)
@@ -59,7 +63,7 @@ if(PROJECT_BUILD)
winspool winspool
ws2_32 ws2_32
) )
else() elseif(NOT PROJECT_IS_DARWIN)
link_libraries( link_libraries(
uring uring
) )

View File

@@ -39,6 +39,14 @@ if(PROJECT_ENABLE_BOOST)
wserialization wserialization
) )
else() else()
if(PROJECT_IS_DARWIN)
set(CMAKE_HAVE_THREADS_LIBRARY 1)
set(CMAKE_THREAD_LIBS_INIT "-lpthread")
set(CMAKE_USE_PTHREADS_INIT 1)
set(CMAKE_USE_WIN32_THREADS_INIT 0)
set(THREADS_PREFER_PTHREAD_FLAG ON)
endif()
find_package(Boost ${BOOST_MAJOR_VERSION}.${BOOST_MINOR_VERSION}.${BOOST_PATCH_VERSION} find_package(Boost ${BOOST_MAJOR_VERSION}.${BOOST_MINOR_VERSION}.${BOOST_PATCH_VERSION}
REQUIRED REQUIRED
COMPONENTS COMPONENTS
@@ -54,7 +62,6 @@ if(PROJECT_ENABLE_BOOST)
random random
regex regex
serialization serialization
system
thread thread
wserialization wserialization
) )
@@ -120,10 +127,12 @@ if(PROJECT_ENABLE_BOOST)
--with-libraries=atomic,chrono,date_time,filesystem,iostreams,locale,log,program_options,random,regex,serialization,system,test,thread --with-libraries=atomic,chrono,date_time,filesystem,iostreams,locale,log,program_options,random,regex,serialization,system,test,thread
BUILD_COMMAND BUILD_COMMAND
./b2 ./b2
-sNO_BZIP2=1
-j$ENV{CMAKE_BUILD_PARALLEL_LEVEL} -j$ENV{CMAKE_BUILD_PARALLEL_LEVEL}
${BOOST_BUILD_ARGS} ${BOOST_BUILD_ARGS}
INSTALL_COMMAND INSTALL_COMMAND
./b2 ./b2
-sNO_BZIP2=1
-j$ENV{CMAKE_BUILD_PARALLEL_LEVEL} -j$ENV{CMAKE_BUILD_PARALLEL_LEVEL}
${BOOST_BUILD_ARGS} ${BOOST_BUILD_ARGS}
install install
@@ -131,6 +140,10 @@ if(PROJECT_ENABLE_BOOST)
list(APPEND PROJECT_DEPENDENCIES boost_project) list(APPEND PROJECT_DEPENDENCIES boost_project)
if(PROJECT_IS_DARWIN OR PROJECT_REQUIRE_ALPINE)
add_dependencies(boost_project icu_project)
endif()
if (NOT CMAKE_HOST_WIN32) if (NOT CMAKE_HOST_WIN32)
add_dependencies(boost_project openssl_project) add_dependencies(boost_project openssl_project)
endif() endif()

View File

@@ -15,6 +15,7 @@ if(PROJECT_ENABLE_CPP_HTTPLIB)
CMAKE_ARGS ${PROJECT_EXTERNAL_CMAKE_FLAGS} CMAKE_ARGS ${PROJECT_EXTERNAL_CMAKE_FLAGS}
-DBUILD_SHARED_LIBS=${PROJECT_BUILD_SHARED_LIBS} -DBUILD_SHARED_LIBS=${PROJECT_BUILD_SHARED_LIBS}
-DBUILD_STATIC_LIBS=ON -DBUILD_STATIC_LIBS=ON
-DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
-DHTTPLIB_REQUIRE_BROTLI=OFF -DHTTPLIB_REQUIRE_BROTLI=OFF
-DHTTPLIB_REQUIRE_OPENSSL=ON -DHTTPLIB_REQUIRE_OPENSSL=ON
-DHTTPLIB_REQUIRE_ZLIB=ON -DHTTPLIB_REQUIRE_ZLIB=ON

View File

@@ -27,8 +27,8 @@ if(PROJECT_ENABLE_CURL)
-DBUILD_SHARED_LIBS=${PROJECT_BUILD_SHARED_LIBS} -DBUILD_SHARED_LIBS=${PROJECT_BUILD_SHARED_LIBS}
-DBUILD_STATIC_CURL=ON -DBUILD_STATIC_CURL=ON
-DBUILD_STATIC_LIBS=ON -DBUILD_STATIC_LIBS=ON
-DBUILD_STATIC_LIBS=ON
-DBUILD_TESTING=OFF -DBUILD_TESTING=OFF
-DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
-DCURL_BROTLI=OFF -DCURL_BROTLI=OFF
-DCURL_CA_BUNDLE=./cacert.pem -DCURL_CA_BUNDLE=./cacert.pem
-DCURL_CA_FALLBACK=ON -DCURL_CA_FALLBACK=ON
@@ -37,11 +37,13 @@ if(PROJECT_ENABLE_CURL)
-DCURL_USE_LIBSSH2=OFF -DCURL_USE_LIBSSH2=OFF
-DCURL_USE_OPENSSL=${PROJECT_ENABLE_OPENSSL} -DCURL_USE_OPENSSL=${PROJECT_ENABLE_OPENSSL}
-DCURL_ZLIB=ON -DCURL_ZLIB=ON
-DCURL_ZSTD=OFF
-DENABLE_CURL_MANUAL=OFF -DENABLE_CURL_MANUAL=OFF
-DENABLE_THREADED_RESOLVER=ON -DENABLE_THREADED_RESOLVER=ON
-DOPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR} -DOPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR}
-DOPENSSL_USE_STATIC_LIBS=${OPENSSL_USE_STATIC_LIBS} -DOPENSSL_USE_STATIC_LIBS=${OPENSSL_USE_STATIC_LIBS}
-DUSE_LIBIDN2=OFF -DUSE_LIBIDN2=OFF
-DUSE_NGHTTP2=OFF
-DZLIB_USE_STATIC_LIBS=${ZLIB_USE_STATIC_LIBS} -DZLIB_USE_STATIC_LIBS=${ZLIB_USE_STATIC_LIBS}
) )

View File

@@ -19,6 +19,13 @@ if(PROJECT_ENABLE_FUSE AND NOT PROJECT_IS_MINGW)
link_libraries(fuse) link_libraries(fuse)
endif() endif()
endif() endif()
else()
if (PROJECT_IS_DARWIN)
find_library(OSXFUSE NO_CACHE NAMES OSXFUSE)
if (NOT OSXFUSE)
message(FATAL_ERROR "FUSE for macOS not found (https://macfuse.github.io)")
endif ()
set(PROJECT_FUSE fuse2)
else() else()
pkg_check_modules(LIBFUSE3 fuse3>=3.0.0) pkg_check_modules(LIBFUSE3 fuse3>=3.0.0)
if(LIBFUSE3_FOUND) if(LIBFUSE3_FOUND)
@@ -34,4 +41,5 @@ if(PROJECT_ENABLE_FUSE AND NOT PROJECT_IS_MINGW)
endif() endif()
endif() endif()
endif() endif()
endif()
endif() endif()

24
cmake/libraries/icu.cmake Normal file
View File

@@ -0,0 +1,24 @@
if((PROJECT_IS_DARWIN OR PROJECT_REQUIRE_ALPINE) AND NOT PROJECT_IS_MINGW AND NOT PROJECT_BUILD)
if(PROJECT_BUILD_SHARED_LIBS)
set(ICU_ENABLE_SHARED yes)
else()
set(ICU_ENABLE_SHARED no)
endif()
ExternalProject_Add(icu_project
PREFIX external
URL ${PROJECT_3RD_PARTY_DIR}/mingw64/icu-release-${ICU_VERSION}.tar.gz
URL_HASH SHA256=${ICU_HASH}
BUILD_IN_SOURCE 1
LIST_SEPARATOR |
PATCH_COMMAND chmod +x ${PROJECT_3RD_PARTY_DIR}/icu_configure.sh
CONFIGURE_COMMAND cd icu4c/source && ${PROJECT_3RD_PARTY_DIR}/icu_configure.sh
${PROJECT_MARCH}
${PROJECT_EXTERNAL_BUILD_ROOT}
${ICU_ENABLE_SHARED}
BUILD_COMMAND cd icu4c/source && make -j$ENV{CMAKE_BUILD_PARALLEL_LEVEL}
INSTALL_COMMAND cd icu4c/source && make install
)
list(APPEND PROJECT_DEPENDENCIES icu_project)
endif()

View File

@@ -18,6 +18,7 @@ if(PROJECT_ENABLE_JSON)
CMAKE_ARGS ${PROJECT_EXTERNAL_CMAKE_FLAGS} CMAKE_ARGS ${PROJECT_EXTERNAL_CMAKE_FLAGS}
-DBUILD_SHARED_LIBS=${PROJECT_BUILD_SHARED_LIBS} -DBUILD_SHARED_LIBS=${PROJECT_BUILD_SHARED_LIBS}
-DBUILD_STATIC_LIBS=ON -DBUILD_STATIC_LIBS=ON
-DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
-DJSON_BuildTests=OFF -DJSON_BuildTests=OFF
-DJSON_Install=ON -DJSON_Install=ON
-DJSON_MultipleHeaders=OFF -DJSON_MultipleHeaders=OFF

View File

@@ -15,6 +15,12 @@ if(PROJECT_ENABLE_OPENSSL)
elseif(NOT PROJECT_IS_MINGW) elseif(NOT PROJECT_IS_MINGW)
if(PROJECT_IS_MINGW) if(PROJECT_IS_MINGW)
set(OPENSSL_COMPILE_TYPE mingw64) set(OPENSSL_COMPILE_TYPE mingw64)
elseif(PROJECT_IS_DARWIN)
if(PROJECT_IS_ARM64)
set(OPENSSL_COMPILE_TYPE darwin64-arm64)
else()
set(OPENSSL_COMPILE_TYPE darwin64-x86_64)
endif()
elseif(PROJECT_IS_ARM64) elseif(PROJECT_IS_ARM64)
set(OPENSSL_COMPILE_TYPE linux-aarch64) set(OPENSSL_COMPILE_TYPE linux-aarch64)
else() else()

View File

@@ -20,6 +20,7 @@ if(PROJECT_ENABLE_PUGIXML)
CMAKE_ARGS ${PROJECT_EXTERNAL_CMAKE_FLAGS} CMAKE_ARGS ${PROJECT_EXTERNAL_CMAKE_FLAGS}
-DBUILD_SHARED_LIBS=${PROJECT_BUILD_SHARED_LIBS} -DBUILD_SHARED_LIBS=${PROJECT_BUILD_SHARED_LIBS}
-DBUILD_STATIC_LIBS=ON -DBUILD_STATIC_LIBS=ON
-DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
) )
list(APPEND PROJECT_DEPENDENCIES pugixml_project) list(APPEND PROJECT_DEPENDENCIES pugixml_project)

View File

@@ -14,12 +14,14 @@ if(PROJECT_ENABLE_ROCKSDB)
CMAKE_ARGS ${PROJECT_EXTERNAL_CMAKE_FLAGS} CMAKE_ARGS ${PROJECT_EXTERNAL_CMAKE_FLAGS}
-DBUILD_SHARED_LIBS=OFF -DBUILD_SHARED_LIBS=OFF
-DBUILD_STATIC_LIBS=ON -DBUILD_STATIC_LIBS=ON
-DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
-DFAIL_ON_WARNINGS=OFF -DFAIL_ON_WARNINGS=OFF
-DPORTABLE=1 -DPORTABLE=1
-DROCKSDB_BUILD_SHARED=OFF -DROCKSDB_BUILD_SHARED=OFF
-DROCKSDB_INSTALL_ON_WINDOWS=ON -DROCKSDB_INSTALL_ON_WINDOWS=ON
-DWITH_BENCHMARK=OFF -DWITH_BENCHMARK=OFF
-DWITH_BENCHMARK_TOOLS=OFF -DWITH_BENCHMARK_TOOLS=OFF
-DWITH_BZ2=OFF
-DWITH_CORE_TOOLS=OFF -DWITH_CORE_TOOLS=OFF
-DWITH_EXAMPLES=OFF -DWITH_EXAMPLES=OFF
-DWITH_GFLAGS=OFF -DWITH_GFLAGS=OFF

View File

@@ -15,6 +15,7 @@ if(PROJECT_ENABLE_SPDLOG)
LIST_SEPARATOR | LIST_SEPARATOR |
CMAKE_ARGS ${PROJECT_EXTERNAL_CMAKE_FLAGS} CMAKE_ARGS ${PROJECT_EXTERNAL_CMAKE_FLAGS}
-DBUILD_SHARED_LIBS=${PROJECT_BUILD_SHARED_LIBS} -DBUILD_SHARED_LIBS=${PROJECT_BUILD_SHARED_LIBS}
-DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
-DSPDLOG_BUILD_EXAMPLE=OFF -DSPDLOG_BUILD_EXAMPLE=OFF
-DSPDLOG_FMT_EXTERNAL=OFF -DSPDLOG_FMT_EXTERNAL=OFF
-DSPDLOG_FMT_EXTERNAL_HO=OFF -DSPDLOG_FMT_EXTERNAL_HO=OFF

View File

@@ -16,6 +16,7 @@ if(PROJECT_ENABLE_STDUUID)
CMAKE_ARGS ${PROJECT_EXTERNAL_CMAKE_FLAGS} CMAKE_ARGS ${PROJECT_EXTERNAL_CMAKE_FLAGS}
-DBUILD_SHARED_LIBS=${PROJECT_BUILD_SHARED_LIBS} -DBUILD_SHARED_LIBS=${PROJECT_BUILD_SHARED_LIBS}
-DBUILD_STATIC_LIBS=ON -DBUILD_STATIC_LIBS=ON
-DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
-DUUID_BUILD_TESTS=OFF -DUUID_BUILD_TESTS=OFF
-DUUID_ENABLE_INSTALL=ON -DUUID_ENABLE_INSTALL=ON
-DUUID_USING_CXX20_SPAN=ON -DUUID_USING_CXX20_SPAN=ON

View File

@@ -10,6 +10,7 @@ if (PROJECT_ENABLE_TESTING)
CMAKE_ARGS ${PROJECT_EXTERNAL_CMAKE_FLAGS} CMAKE_ARGS ${PROJECT_EXTERNAL_CMAKE_FLAGS}
-DBUILD_SHARED_LIBS=${PROJECT_BUILD_SHARED_LIBS} -DBUILD_SHARED_LIBS=${PROJECT_BUILD_SHARED_LIBS}
-DBUILD_STATIC_LIBS=ON -DBUILD_STATIC_LIBS=ON
-DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES}
) )
list(APPEND PROJECT_DEPENDENCIES gtest_project) list(APPEND PROJECT_DEPENDENCIES gtest_project)

View File

@@ -2,10 +2,6 @@ if(MSVC)
message(FATAL_ERROR "MSVC will not be supported") message(FATAL_ERROR "MSVC will not be supported")
endif() endif()
if(UNIX AND APPLE)
message(FATAL_ERROR "Apple is not currently supported")
endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
message(FATAL_ERROR "FreeBSD is not currently supported") message(FATAL_ERROR "FreeBSD is not currently supported")
endif() endif()
@@ -13,3 +9,15 @@ endif()
if(PROJECT_REQUIRE_ALPINE AND NOT PROJECT_IS_ALPINE AND PROJECT_IS_MINGW AND PROJECT_IS_MINGW_UNIX) if(PROJECT_REQUIRE_ALPINE AND NOT PROJECT_IS_ALPINE AND PROJECT_IS_MINGW AND PROJECT_IS_MINGW_UNIX)
message(FATAL_ERROR "Project requires Alpine Linux to build") message(FATAL_ERROR "Project requires Alpine Linux to build")
endif() endif()
if (PROJECT_IS_DARWIN)
if (PROJECT_IS_ARM64)
set(CMAKE_OSX_ARCHITECTURES "arm64")
else()
set(CMAKE_OSX_ARCHITECTURES "x86_64")
endif()
endif()
if (PROJECT_IS_DARWIN AND NOT PROJECT_MACOS_BUNDLE_ID)
message(FATAL_ERROR "'PROJECT_MACOS_BUNDLE_ID' is not set in 'config.sh'")
endif()

View File

@@ -3,25 +3,28 @@ set(BOOST2_MAJOR_VERSION 1)
set(BOOST2_MINOR_VERSION 76) set(BOOST2_MINOR_VERSION 76)
set(BOOST2_PATCH_VERSION 0) set(BOOST2_PATCH_VERSION 0)
set(BOOST_MAJOR_VERSION 1) set(BOOST_MAJOR_VERSION 1)
set(BOOST_MINOR_VERSION 88) set(BOOST_MINOR_VERSION 89)
set(BOOST_PATCH_VERSION 0) set(BOOST_PATCH_VERSION 0)
set(CPP_HTTPLIB_VERSION 0.23.1) set(CPP_HTTPLIB_VERSION 0.26.0)
set(CURL2_VERSION 8_15_0) set(CURL2_VERSION 8_16_0)
set(CURL_VERSION 8.15.0) set(CURL_VERSION 8.16.0)
set(EXPAT2_VERSION 2_7_1) set(EXPAT2_VERSION 2_7_1)
set(EXPAT_VERSION 2.7.1) set(EXPAT_VERSION 2.7.1)
set(GCC_VERSION 15.1.0) set(GCC_VERSION 15.2.0)
set(GTEST_VERSION 1.17.0) set(GTEST_VERSION 1.17.0)
set(ICU_VERSION 76-1) set(ICU_VERSION 76-1)
set(INNOSETUP_VERSION 6.5.4)
set(JSON_VERSION 3.12.0) set(JSON_VERSION 3.12.0)
set(LIBSODIUM_VERSION 1.0.20) set(LIBSODIUM_VERSION 1.0.20)
set(MINGW_VERSION 13.0.0) set(MINGW_VERSION 13.0.0)
set(OPENSSL_VERSION 3.5.1) set(OPENSSL_VERSION 3.6.0)
set(PKG_CONFIG_VERSION 0.29.2) set(PKG_CONFIG_VERSION 0.29.2)
set(PUGIXML_VERSION 1.15) set(PUGIXML_VERSION 1.15)
set(ROCKSDB_VERSION 10.4.2) set(ROCKSDB_VERSION 10.5.1)
set(SPDLOG_VERSION 1.15.3) set(SPDLOG_VERSION 1.15.3)
set(SQLITE2_VERSION 3.50.3) set(SQLITE2_VERSION 3.50.4)
set(SQLITE_VERSION 3500300) set(SQLITE_VERSION 3500400)
set(STDUUID_VERSION 1.2.3) set(STDUUID_VERSION 1.2.3)
set(WINFSP2_VERSION 2.1)
set(WINFSP_VERSION 2.1.25156)
set(ZLIB_VERSION 1.3.1) set(ZLIB_VERSION 1.3.1)

View File

@@ -8,11 +8,14 @@ PROJECT_URL="${PROJECT_COMPANY_NAME}/repertory"
PROJECT_COPYRIGHT="Copyright <2018-2025> <MIT License> <${PROJECT_URL}>" PROJECT_COPYRIGHT="Copyright <2018-2025> <MIT License> <${PROJECT_URL}>"
PROJECT_DESC="Mount utility for Sia and S3" PROJECT_DESC="Mount utility for Sia and S3"
PROJECT_MACOS_BUNDLE_ID="com.fifthgrid.blockstorage.repertory"
PROJECT_MACOS_ICNS_NAME="icon.icns"
PROJECT_MAJOR_VERSION=2 PROJECT_MAJOR_VERSION=2
PROJECT_MINOR_VERSION=0 PROJECT_MINOR_VERSION=1
PROJECT_REVISION_VERSION=7 PROJECT_REVISION_VERSION=0
PROJECT_RELEASE_NUM=1 PROJECT_RELEASE_NUM=1
PROJECT_RELEASE_ITER=release PROJECT_RELEASE_ITER=rc
PROJECT_APP_LIST=(${PROJECT_NAME}) PROJECT_APP_LIST=(${PROJECT_NAME})

View File

@@ -1,5 +1,5 @@
#comment #comment
FROM arm64v8/alpine:3.21.4 FROM arm64v8/alpine:3.22.2
MAINTAINER Scott E. Graves <scott.e.graves@protonmail.com> MAINTAINER Scott E. Graves <scott.e.graves@protonmail.com>
CMD bash CMD bash
@@ -32,9 +32,6 @@ RUN apk add \
gflags-dev \ gflags-dev \
git \ git \
git-lfs \ git-lfs \
icu-dev \
icu-libs \
icu-static \
libogg-dev \ libogg-dev \
libogg-static \ libogg-static \
libtool \ libtool \

View File

@@ -1,5 +1,5 @@
#comment #comment
FROM alpine:3.21.4 FROM alpine:3.22.2
MAINTAINER Scott E. Graves <scott.e.graves@protonmail.com> MAINTAINER Scott E. Graves <scott.e.graves@protonmail.com>
CMD bash CMD bash
@@ -32,9 +32,6 @@ RUN apk add \
gflags-dev \ gflags-dev \
git \ git \
git-lfs \ git-lfs \
icu-dev \
icu-libs \
icu-static \
libogg-dev \ libogg-dev \
libogg-static \ libogg-static \
libtool \ libtool \

View File

@@ -11,7 +11,6 @@ RUN apt-get install -y \
gdb \ gdb \
git \ git \
lib32stdc++6 \ lib32stdc++6 \
libgconf-2-4 \
libglu1-mesa \ libglu1-mesa \
libstdc++6 \ libstdc++6 \
python3 \ python3 \

View File

@@ -1,5 +1,5 @@
#comment #comment
FROM alpine:3.21.4 FROM alpine:3.22.2
RUN apk update RUN apk update
RUN apk upgrade RUN apk upgrade
@@ -12,6 +12,7 @@ RUN apk add \
bzip2 \ bzip2 \
clang17-extra-tools \ clang17-extra-tools \
cmake \ cmake \
curl \
file \ file \
flex \ flex \
g++ \ g++ \
@@ -43,6 +44,7 @@ RUN apk add \
ruby \ ruby \
texinfo \ texinfo \
unzip \ unzip \
xvfb \
wget \ wget \
wine \ wine \
xz \ xz \
@@ -102,6 +104,39 @@ RUN echo -e \
"system = 'windows'\n"\ "system = 'windows'\n"\
> ${MY_TOOLCHAIN_FILE_MESON} > ${MY_TOOLCHAIN_FILE_MESON}
RUN mkdir -p /opt/bin;echo -e \
"#!/bin/sh\n"\
"COUNT=0\n"\
"echo \"Start waiting on \$@\"\n"\
"while pgrep \"\$@\" > /dev/null; do \n"\
" echo \"waiting ...\"\n"\
" sleep 1;\n"\
" COUNT=\$((COUNT+1))\n"\
" if [ \$COUNT -eq 60 ]; then\n"\
" exit 3;\n"\
" fi\n"\
"done\n"\
"echo \"\$@ completed\"\n"\
> /opt/bin/waitonprocess && \
chmod +x /opt/bin/waitonprocess && \
cat /opt/bin/waitonprocess
RUN echo -e \
"#!/bin/sh\n"\
"Xvfb \$DISPLAY &\n"\
"tokill=\$!\n"\
"wine wineboot --init\n"\
"waitonprocess wineserver\n"\
"\"\$@\"\n"\
"retval=\$?\n"\
"kill -15 \$tokill\n"\
"wine wineboot --shutdown\n"\
"return \$retval\n"\
> /opt/bin/wine-x11-run && \
chmod +x /opt/bin/wine-x11-run && \
cat /opt/bin/wine-x11-run
ENV PATH="/opt/bin:${PATH}"
SHELL [ "/bin/bash", "-c" ] SHELL [ "/bin/bash", "-c" ]
RUN mkdir -p \ RUN mkdir -p \
@@ -711,6 +746,7 @@ RUN if [ -f "/3rd_party/cpp-httplib-${MY_CPP_HTTPLIB_VERSION}.tar.gz" ]; then \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_STANDARD=${MY_CXX_STANDARD} \ -DCMAKE_CXX_STANDARD=${MY_CXX_STANDARD} \
-DCMAKE_INSTALL_PREFIX=${MY_MINGW_DIR} \ -DCMAKE_INSTALL_PREFIX=${MY_MINGW_DIR} \
-DCMAKE_SYSTEM_VERSION="10.0.0" \
-DCMAKE_TOOLCHAIN_FILE=${MY_TOOLCHAIN_FILE_CMAKE} \ -DCMAKE_TOOLCHAIN_FILE=${MY_TOOLCHAIN_FILE_CMAKE} \
-DHTTPLIB_REQUIRE_BROTLI=OFF \ -DHTTPLIB_REQUIRE_BROTLI=OFF \
-DHTTPLIB_REQUIRE_OPENSSL=ON \ -DHTTPLIB_REQUIRE_OPENSSL=ON \
@@ -799,6 +835,7 @@ RUN if [ -f "/3rd_party/libevent-${MY_LIBEVENT_VERSION}-stable.tar.gz" ]; then \
&& cmake .. \ && cmake .. \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_STANDARD=${MY_CXX_STANDARD} \ -DCMAKE_CXX_STANDARD=${MY_CXX_STANDARD} \
-DCMAKE_C_FLAGS="-include winsock2.h -include ws2tcpip.h -include iphlpapi.h" \
-DCMAKE_INSTALL_PREFIX=${MY_MINGW_DIR} \ -DCMAKE_INSTALL_PREFIX=${MY_MINGW_DIR} \
-DCMAKE_TOOLCHAIN_FILE=${MY_TOOLCHAIN_FILE_CMAKE} \ -DCMAKE_TOOLCHAIN_FILE=${MY_TOOLCHAIN_FILE_CMAKE} \
-DEVENT__DISABLE_OPENSSL=ON \ -DEVENT__DISABLE_OPENSSL=ON \
@@ -888,6 +925,7 @@ RUN if [ -f "/3rd_party/rocksdb-${MY_ROCKSDB_VERSION}.tar.gz" ]; then \
-DROCKSDB_INSTALL_ON_WINDOWS=ON \ -DROCKSDB_INSTALL_ON_WINDOWS=ON \
-DWITH_BENCHMARK=OFF \ -DWITH_BENCHMARK=OFF \
-DWITH_BENCHMARK_TOOLS=OFF \ -DWITH_BENCHMARK_TOOLS=OFF \
-DWITH_BZ2=OFF \
-DWITH_CORE_TOOLS=OFF \ -DWITH_CORE_TOOLS=OFF \
-DWITH_EXAMPLES=OFF \ -DWITH_EXAMPLES=OFF \
-DWITH_GFLAGS=OFF \ -DWITH_GFLAGS=OFF \
@@ -1119,6 +1157,33 @@ RUN if [ -f "/3rd_party/libdsm-${MY_LIBDSM_VERSION}.tar.gz" ]; then \
&& rm -r libdsm-${MY_LIBDSM_VERSION} \ && rm -r libdsm-${MY_LIBDSM_VERSION} \
; fi ; fi
RUN (mv ${MY_MINGW_DIR}/lib/*.dll ${MY_MINGW_DIR}/bin || echo "no dll's found") \ ENV DISPLAY=:90
ENV WINEDEBUG=-all,err+all
ARG INNOSETUP_VERSION
ENV MY_INNOSETUP_VERSION=${INNOSETUP_VERSION}
RUN rm -rf /root/.wine; \
wine64 reg add 'HKEY_CURRENT_USER\Software\Wine' /v ShowDotFiles /d Y \
&& while [ ! -f /root/.wine/user.reg ]; do sleep 1; done; \
wine-x11-run wine64 /3rd_party/mingw64/innosetup-${MY_INNOSETUP_VERSION}.exe /SP- /VERYSILENT /ALLUSERS /SUPPRESSMSGBOXES /DOWNLOADISCRYPT=1
ARG UID=1000
ARG GID=1000
ARG USERNAME=myuser
RUN delgroup scanner || echo "no scanner group found"
RUN addgroup -g $GID $USERNAME && \
adduser -D -u $UID -G $USERNAME -h /home/$USERNAME $USERNAME
RUN rsync -av --progress /root/.wine/ /home/$USERNAME/.wine/ && \
chown -R $UID:$GID -R /home/$USERNAME/.wine/
RUN (cp ${MY_MINGW_DIR}/lib/*.dll ${MY_MINGW_DIR}/bin || echo "no dll's found") \
&& chmod 0777 -R ${MY_MINGW_DIR} \ && chmod 0777 -R ${MY_MINGW_DIR} \
&& rm -rf /3rd_party && rm -rf /3rd_party \
&& rm -rf /root/.wine
USER $USERNAME
WORKDIR /home/$USERNAME

View File

@@ -8,3 +8,7 @@ rsync -av --progress ${CURRENT_DIR}/${PROJECT_NAME}/${PROJECT_NAME}_test/test_in
rsync -av --progress ${CURRENT_DIR}/${PROJECT_NAME}/${PROJECT_NAME}_test/test_input/ \ rsync -av --progress ${CURRENT_DIR}/${PROJECT_NAME}/${PROJECT_NAME}_test/test_input/ \
${PROJECT_DIST_DIR}/test_input/ ${PROJECT_DIST_DIR}/test_input/
rsync -av --progress ${CURRENT_DIR}/assets/icon.ico ${PROJECT_DIST_DIR}/icon.ico
rsync -av --progress ${CURRENT_DIR}/assets/blue/logo.iconset/icon_128x128.png ${PROJECT_DIST_DIR}/repertory.png

View File

@@ -1,7 +1,20 @@
set(CMAKE_CXX_FLAGS "-include common.hpp ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "-include common.hpp ${CMAKE_CXX_FLAGS}")
if (PROJECT_IS_DARWIN)
configure_file(
${CMAKE_SOURCE_DIR}/${PROJECT_NAME}/Info.plist.in
${CMAKE_SOURCE_DIR}/${PROJECT_NAME}/Info.plist
@ONLY
)
endif()
add_project_library(lib${PROJECT_NAME} "" "" "${PROJECT_ADDITIONAL_SOURCES}") add_project_library(lib${PROJECT_NAME} "" "" "${PROJECT_ADDITIONAL_SOURCES}")
add_project_executable(${PROJECT_NAME} lib${PROJECT_NAME} lib${PROJECT_NAME}) add_project_executable(${PROJECT_NAME} lib${PROJECT_NAME} lib${PROJECT_NAME})
if (PROJECT_IS_DARWIN)
set_target_properties(${PROJECT_NAME} PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}/Info.plist
)
endif()
add_project_test_executable(${PROJECT_NAME}_test lib${PROJECT_NAME} lib${PROJECT_NAME}) add_project_test_executable(${PROJECT_NAME}_test lib${PROJECT_NAME} lib${PROJECT_NAME})

23
repertory/Info.plist.in Normal file
View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>@PROJECT_NAME@</string>
<key>CFBundleIdentifier</key>
<string>@PROJECT_MACOS_BUNDLE_ID@</string>
<key>CFBundleName</key>
<string>@PROJECT_NAME@</string>
<key>CFBundleVersion</key>
<string>@PROJECT_MAJOR_VERSION@.@PROJECT_MINOR_VERSION@.@PROJECT_REVISION_VERSION@-@PROJECT_RELEASE_ITER@_@PROJECT_GIT_REV@</string>
<key>CFBundleShortVersionString</key>
<string>@PROJECT_MAJOR_VERSION@.@PROJECT_MINOR_VERSION@.@PROJECT_REVISION_VERSION@.@PROJECT_RELEASE_NUM@</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>LSUIElement</key>
<true />
<key>CFBundleIconFile</key>
<string>@PROJECT_MACOS_ICNS_NAME@</string>
</dict>
</plist>

View File

@@ -0,0 +1,421 @@
#!/usr/bin/env bash
# No `-e` (we tolerate benign non-zero returns); keep -Euo
set -Euo pipefail
LOG_DIR="/tmp"
LOG_FILE="${LOG_DIR}/Install-$(date +%Y%m%d-%H%M%S).log"
exec > >(tee -a "$LOG_FILE") 2>&1
echo "Logging to: $LOG_FILE"
TARGET_DIR="/Applications"
APP_NAME="repertory.app"
# Embedded at pack time (from CFBundleIdentifier prefix)
LABEL_PREFIX="__LABEL_PREFIX__"
UI_LABEL="${LABEL_PREFIX}.ui"
staged=""
backup=""
snapfile=""
skip_ui_launch=0
log() { printf "[%(%H:%M:%S)T] %s\n" -1 "$*"; }
warn() { log "WARN: $*"; }
die() {
log "ERROR: $*"
exit 2
}
here="$(cd "$(dirname "$0")" && pwd)"
# Locate source app on the DMG (supports hidden payload dirs)
src_app="${here}/${APP_NAME}"
if [[ ! -d "$src_app" ]]; then
src_app="$(/usr/bin/find "$here" -type d -name "$APP_NAME" -print -quit 2>/dev/null || true)"
fi
[[ -d "$src_app" ]] || die "Could not find ${APP_NAME} on this disk image."
app_basename="$(basename "$src_app")"
dest_app="${TARGET_DIR}/${APP_NAME}"
bundle_id_of() { /usr/bin/defaults read "$1/Contents/Info" CFBundleIdentifier 2>/dev/null || true; }
bundle_exec_of() { /usr/bin/defaults read "$1/Contents/Info" CFBundleExecutable 2>/dev/null || echo "${app_basename%.app}"; }
bundle_version_of() {
/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$1/Contents/Info.plist" 2>/dev/null ||
/usr/bin/defaults read "$1/Contents/Info" CFBundleShortVersionString 2>/dev/null || echo "(unknown)"
}
bundle_build_of() {
/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' "$1/Contents/Info.plist" 2>/dev/null ||
/usr/bin/defaults read "$1/Contents/Info" CFBundleVersion 2>/dev/null || echo "(unknown)"
}
# Require /Applications; prompt for sudo if needed; abort if cannot elevate
USE_SUDO=0
SUDO=""
ensure_target_writable() {
if mkdir -p "${TARGET_DIR}/.repertory_install_test.$$" 2>/dev/null; then
rmdir "${TARGET_DIR}/.repertory_install_test.$$" 2>/dev/null || true
USE_SUDO=0
SUDO=""
return 0
fi
if command -v sudo >/dev/null 2>&1; then
log "Elevating privileges to write to ${TARGET_DIR}…"
sudo -v || die "Administrator privileges required to install into ${TARGET_DIR}."
USE_SUDO=1
SUDO="sudo"
return 0
fi
die "Cannot write to ${TARGET_DIR} and sudo is unavailable."
}
# ----- STRICT LABEL PREFIX GATE (fail if invalid) -----
_is_valid_label_prefix() {
local p="${1:-}"
[[ -n "$p" ]] && [[ "$p" != "__LABEL_PREFIX__" ]] && [[ "$p" =~ ^[A-Za-z0-9._-]+$ ]] && [[ "$p" == *.* ]]
}
if ! _is_valid_label_prefix "${LABEL_PREFIX:-}"; then
die "Invalid LABEL_PREFIX in installer (value: \"${LABEL_PREFIX:-}\"). Rebuild the DMG so the installer contains a valid reverse-DNS prefix."
fi
# ----- LaunchServices helpers -----
ls_prune_bundle_id() {
local bundle_id="$1" keep_path="$2"
[[ -z "$bundle_id" ]] && return 0
local search_roots=("/Applications" "$HOME/Applications" "/Volumes")
if [[ -n "${here:-}" && "$here" == /Volumes/* ]]; then search_roots+=("$here"); fi
local candidates=""
for root in "${search_roots[@]}"; do
[[ -d "$root" ]] || continue
candidates+=$'\n'"$(/usr/bin/mdfind -onlyin "$root" "kMDItemCFBundleIdentifier == '${bundle_id}'" 2>/dev/null || true)"
done
# Include backups adjacent to keep_path (quote-safe)
local parent_dir="${keep_path%/*.app}"
candidates+=$'\n'$(/bin/ls -1d "${parent_dir}/"*.bak 2>/dev/null || true)
local LSREG="/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister"
printf "%s\n" "$candidates" | /usr/bin/awk 'NF' | /usr/bin/sort -u | while IFS= read -r p; do
[[ -z "$p" || ! -d "$p" || "$p" == "$keep_path" ]] && continue
log "Unregistering older LS entry for ${bundle_id}: $p"
"$LSREG" -u "$p" >/dev/null 2>&1 || true
done
}
# ----- FUSE unmount (no process killing here) -----
is_mounted() { /sbin/mount | /usr/bin/awk '{print $3}' | /usr/bin/grep -Fx "${1:-}" >/dev/null 2>&1; }
_list_repertory_fuse_mounts() { /sbin/mount | /usr/bin/grep -Ei 'macfuse|osxfuse' | /usr/bin/awk '{print $3}' | /usr/bin/grep -i "repertory" || true; }
_unmount_one() {
local mnt="${1:-}"
[[ -n "$mnt" ]] || return 0
/usr/sbin/diskutil unmount "$mnt" >/dev/null 2>&1 || /sbin/umount "$mnt" >/dev/null 2>&1 || true
if is_mounted "$mnt"; then
/usr/sbin/diskutil unmount force "$mnt" >/dev/null 2>&1 || /sbin/umount -f "$mnt" >/dev/null 2>&1 || true
fi
for _ in {1..20}; do
is_mounted "$mnt" || return 0
sleep 0.25
done
return 1
}
unmount_existing_repertory_volumes() {
# Hard-fail on the first unmount problem.
while IFS= read -r mnt; do
[[ -z "$mnt" ]] && continue
log "Unmounting FUSE mount: $mnt"
if ! _unmount_one "$mnt"; then
warn "Failed to unmount $mnt"
return 1
fi
done < <(_list_repertory_fuse_mounts)
sync || true
sleep 0.3
return 0
}
# ----- user LaunchAgents (by LABEL_PREFIX only) -----
get_plist_label() { /usr/bin/defaults read "$1" Label 2>/dev/null || /usr/libexec/PlistBuddy -c "Print :Label" "$1" 2>/dev/null || basename "$1" .plist; }
# Return the executable path a LaunchAgent runs (ProgramArguments[0] or Program).
# Echoes empty string if neither is present.
get_plist_exec_path() {
local plist="$1" arg0=""
# Prefer ProgramArguments[0]
arg0="$(/usr/libexec/PlistBuddy -c 'Print :ProgramArguments:0' "$plist" 2>/dev/null || true)"
if [[ -z "$arg0" ]]; then
# Fallback to Program (older style)
arg0="$(/usr/libexec/PlistBuddy -c 'Print :Program' "$plist" 2>/dev/null || true)"
fi
printf '%s\n' "$arg0"
}
snapshot_launchagents_user() {
local user_agents="$HOME/Library/LaunchAgents"
snapfile="$(/usr/bin/mktemp "/tmp/repertory_launchagents.XXXXXX")" || snapfile=""
if [[ -z "$snapfile" ]]; then
warn "Could not create temporary snapshot file; skipping LaunchAgent restart snapshot."
return 0
fi
[[ -d "$user_agents" ]] || return 0
# We collect non-UI first, then UI last, to preserve restart order later.
local tmp_nonui tmp_ui
tmp_nonui="$(/usr/bin/mktemp "/tmp/repertory_launchagents.nonui.XXXXXX")" || tmp_nonui=""
tmp_ui="$(/usr/bin/mktemp "/tmp/repertory_launchagents.ui.XXXXXX")" || tmp_ui=""
/usr/bin/find "$user_agents" -maxdepth 1 -type f -name "${LABEL_PREFIX}"'*.plist' -print 2>/dev/null |
while IFS= read -r plist; do
[[ -z "$plist" ]] && continue
# Label must match the prefix
local label
label="$(get_plist_label "$plist")"
[[ -n "$label" && "$label" == "${LABEL_PREFIX}"* ]] || continue
# Executable must point into the *installed* app path
local exec_path
exec_path="$(get_plist_exec_path "$plist")"
[[ -n "$exec_path" ]] || continue
# Normalize: only accept absolute paths under $dest_app (e.g. .../repertory.app/Contents/...)
if [[ "$exec_path" != "$dest_app/"* ]]; then
# Not one of ours; skip
continue
fi
# Defer UI label to the end
if [[ "$label" == "$UI_LABEL" ]]; then
[[ -n "$tmp_ui" ]] && printf "%s\t%s\n" "$plist" "$label" >>"$tmp_ui"
else
[[ -n "$tmp_nonui" ]] && printf "%s\t%s\n" "$plist" "$label" >>"$tmp_nonui"
fi
done
# Stitch together: non-UI first, then UI
[[ -s "$tmp_nonui" ]] && /bin/cat "$tmp_nonui" >>"$snapfile"
[[ -s "$tmp_ui" ]] && /bin/cat "$tmp_ui" >>"$snapfile"
[[ -n "$tmp_nonui" ]] && /bin/rm -f "$tmp_nonui" 2>/dev/null || true
[[ -n "$tmp_ui" ]] && /bin/rm -f "$tmp_ui" 2>/dev/null || true
log "Snapshot contains $(/usr/bin/wc -l <"$snapfile" 2>/dev/null || echo 0) LaunchAgent(s)."
}
unload_launchd_helpers_user() {
local uid user_agents
uid="$(id -u)"
user_agents="$HOME/Library/LaunchAgents"
[[ -d "$user_agents" ]] || return 0
while IFS= read -r plist; do
[[ -z "$plist" ]] && continue
local base label
base="$(basename "$plist")"
[[ "$base" == "${LABEL_PREFIX}"* ]] || continue
label="$(get_plist_label "$plist")"
[[ -n "$label" && "$label" == "${LABEL_PREFIX}"* ]] || continue
log "Booting out user label ${label} (${plist})"
/bin/launchctl bootout "gui/${uid}" "$plist" 2>/dev/null ||
/bin/launchctl bootout "gui/${uid}" "$label" 2>/dev/null ||
/bin/launchctl remove "$label" 2>/dev/null || true
done < <(/usr/bin/find "$user_agents" -maxdepth 1 -type f -name "${LABEL_PREFIX}"'*.plist' -print 2>/dev/null)
/bin/launchctl list 2>/dev/null | /usr/bin/awk -v pre="$LABEL_PREFIX" 'NF>=3 && index($3, pre)==1 {print $3}' |
while read -r lbl; do
[[ -z "$lbl" ]] && continue
log "Booting out leftover user label: $lbl"
/bin/launchctl bootout "gui/${uid}" "$lbl" 2>/dev/null || /bin/launchctl remove "$lbl" 2>/dev/null || true
done
}
restart_launchagents_from_snapshot() {
[[ -n "${snapfile:-}" && -f "${snapfile}" ]] || return 0
local uid count=0 ui_seen=0
uid="$(id -u)"
# Pass 1: restart all non-UI agents first
while IFS=$'\t' read -r plist label; do
[[ -n "$plist" && -n "$label" ]] || continue
[[ -f "$plist" ]] || continue
[[ "$label" == "$UI_LABEL" ]] && continue
log "Re-starting LaunchAgent: ${label}"
/bin/launchctl bootstrap "gui/${uid}" "$plist" 2>/dev/null || true
/bin/launchctl kickstart -k "gui/${uid}/${label}" 2>/dev/null || true
((count++)) || true
done <"$snapfile"
# Give helpers a moment to settle (e.g., automounts)
sleep 0.3
# Pass 2: restart the UI agent last (if present in the snapshot)
while IFS=$'\t' read -r plist label; do
[[ -n "$plist" && -n "$label" ]] || continue
[[ -f "$plist" ]] || continue
[[ "$label" == "$UI_LABEL" ]] || continue
log "Re-starting UI LaunchAgent last: ${label}"
/bin/launchctl bootstrap "gui/${uid}" "$plist" 2>/dev/null || true
/bin/launchctl kickstart -k "gui/${uid}/${label}" 2>/dev/null || true
ui_seen=1
((count++)) || true
done <"$snapfile"
log "Re-started ${count} LaunchAgent(s) with prefix ${LABEL_PREFIX}." || true
if ((ui_seen)); then
# If the UI label is active, skip manual open(1).
if /bin/launchctl list | /usr/bin/awk '{print $3}' | /usr/bin/grep -Fxq "$UI_LABEL"; then
log "UI LaunchAgent (${UI_LABEL}) active after restart; skipping manual UI launch."
skip_ui_launch=1
fi
fi
}
# ----- quarantine helper -----
remove_quarantine() {
local path="${1:-}"
if [[ "${USE_SUDO:-0}" == "1" ]]; then
sudo /usr/bin/xattr -dr com.apple.quarantine "$path" 2>/dev/null || true
else
/usr/bin/xattr -dr com.apple.quarantine "$path" 2>/dev/null || true
fi
}
# ----- process helpers -----
kill_repertory_processes() {
local exec_name="$1"
/usr/bin/pkill -TERM -f "$dest_app" >/dev/null 2>&1 || true
/usr/bin/pkill -TERM -x "$exec_name" >/dev/null 2>&1 || true
for _ in {1..20}; do
/usr/bin/pgrep -af "$dest_app" >/dev/null 2>&1 || /usr/bin/pgrep -x "$exec_name" >/dev/null 2>&1 || break
sleep 0.1
done
/usr/bin/pkill -KILL -f "$dest_app" >/dev/null 2>&1 || true
/usr/bin/pkill -KILL -x "$exec_name" >/dev/null 2>&1 || true
}
# ----- visibility helper -----
unhide_path() {
local path="$1"
/usr/bin/chflags -R nohidden "$path" 2>/dev/null || true
/usr/bin/xattr -d -r com.apple.FinderInfo "$path" 2>/dev/null || true
}
# ----- stage / validate / activate / post-activate -----
stage_new_app() {
staged="${dest_app}.new-$$"
log "Staging new app → $staged"
$SUDO /usr/bin/ditto "$src_app" "$staged" || die "ditto to stage failed"
remove_quarantine "$staged"
}
validate_staged_app() {
[[ -f "$staged/Contents/Info.plist" ]] || {
$SUDO /bin/rm -rf "$staged"
die "staged app missing Info.plist"
}
local exe_name_staged
exe_name_staged="$(/usr/bin/defaults read "$staged/Contents/Info" CFBundleExecutable 2>/dev/null || echo "${app_basename%.app}")"
[[ -x "$staged/Contents/MacOS/$exe_name_staged" ]] || {
$SUDO /bin/rm -rf "$staged"
die "staged app missing main executable"
}
}
activate_staged_app() {
if [[ -d "$dest_app" ]]; then
backup="${dest_app}.$(date +%Y%m%d%H%M%S).bak"
log "Moving existing app to backup: $backup"
$SUDO /bin/mv "$dest_app" "$backup" || {
$SUDO /bin/rm -rf "$staged"
die "failed to move existing app out of the way"
}
fi
log "Activating new app → $dest_app"
if ! $SUDO /bin/mv "$staged" "$dest_app"; then
warn "Activation failed; attempting rollback…"
[[ -n "$backup" && -d "$backup" ]] && $SUDO /bin/mv "$backup" "$dest_app" || true
$SUDO /bin/rm -rf "$staged" || true
die "install activation failed"
fi
}
post_activate_cleanup() {
log "Clearing quarantine on installed app…"
remove_quarantine "$dest_app"
log "Clearing hidden flags on installed app…"
unhide_path "$dest_app"
local LSREG="/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister"
[[ -x "$LSREG" ]] && "$LSREG" -f "$dest_app" >/dev/null 2>&1 || true
local BID
BID="$(bundle_id_of "$dest_app")"
ls_prune_bundle_id "$BID" "$dest_app"
log "Installed ${app_basename}: version=$(bundle_version_of "$dest_app") build=$(bundle_build_of "$dest_app")"
}
launch_ui() {
log "Launching the new app…"
/usr/bin/open -n "$dest_app" || warn "open -n by path failed; not falling back to -b to avoid launching a stale copy."
}
remove_backup() {
[[ -n "$backup" && -d "$backup" ]] && {
log "Removing backup: $backup"
$SUDO /bin/rm -rf "$backup" || warn "Could not remove backup (safe to delete manually): $backup"
}
log "Done."
}
cleanup_staged() {
if [[ -n "${staged:-}" && -d "${staged}" ]]; then
log "Cleaning up staged folder: ${staged}"
if [[ "${USE_SUDO:-0}" == "1" ]]; then
sudo /bin/rm -rf "${staged}" 2>/dev/null || true
else
/bin/rm -rf "${staged}" 2>/dev/null || true
fi
fi
if [[ -n "${snapfile:-}" && -f "${snapfile}" ]]; then
/bin/rm -f "${snapfile}" 2>/dev/null || true
fi
}
main() {
ensure_target_writable
local exec_name
exec_name="$(bundle_exec_of "$src_app")"
# 1) Snapshot agents we'll restart later
snapshot_launchagents_user
# 2) Hard-fail if any FUSE unmount fails
unmount_existing_repertory_volumes || die "One or more FUSE mounts resisted unmount."
# 3) Stop user LaunchAgents (do NOT delete plists)
unload_launchd_helpers_user
# 4) Kill any remaining repertory processes
kill_repertory_processes "$exec_name"
# 5) Stage → validate → activate → post-activate
stage_new_app
validate_staged_app
activate_staged_app
post_activate_cleanup
# 6) Re-start previously-running LaunchAgents (so automount helpers come up)
restart_launchagents_from_snapshot
# 7) If UI LaunchAgent came back, skip manual launch
if ((!skip_ui_launch)); then
launch_ui
fi
# 8) Remove backup now that everything is good
remove_backup
}
trap 'rc=$?; cleanup_staged; if (( rc != 0 )); then echo "Installer failed with code $rc. See $LOG_FILE"; fi' EXIT
main "$@"

View File

@@ -31,24 +31,22 @@ private:
static stop_type stop_requested; static stop_type stop_requested;
public: public:
[[nodiscard]] static auto default_agent_name(const provider_type &prov) [[nodiscard]] static auto default_agent_name(provider_type prov)
-> std::string; -> std::string;
[[nodiscard]] static auto default_api_port(const provider_type &prov) [[nodiscard]] static auto default_api_port(provider_type prov)
-> std::uint16_t; -> std::uint16_t;
[[nodiscard]] static auto default_data_directory(const provider_type &prov) [[nodiscard]] static auto default_data_directory(provider_type prov)
-> std::string; -> std::string;
[[nodiscard]] static auto default_remote_api_port(const provider_type &prov) [[nodiscard]] static auto default_remote_api_port(provider_type prov)
-> std::uint16_t; -> std::uint16_t;
[[nodiscard]] static auto default_rpc_port() -> std::uint16_t; [[nodiscard]] static auto get_provider_display_name(provider_type prov)
[[nodiscard]] static auto get_provider_display_name(const provider_type &prov)
-> std::string; -> std::string;
[[nodiscard]] static auto get_provider_name(const provider_type &prov) [[nodiscard]] static auto get_provider_name(provider_type prov)
-> std::string; -> std::string;
[[nodiscard]] static auto get_root_data_directory() -> std::string; [[nodiscard]] static auto get_root_data_directory() -> std::string;
@@ -59,7 +57,7 @@ public:
static void set_stop_requested(); static void set_stop_requested();
public: public:
app_config(const provider_type &prov, std::string_view data_directory = ""); app_config(provider_type prov, std::string_view data_directory);
app_config() = delete; app_config() = delete;
app_config(app_config &&) = delete; app_config(app_config &&) = delete;
@@ -72,10 +70,12 @@ public:
private: private:
provider_type prov_; provider_type prov_;
atomic<std::string> api_password_; utils::atomic<std::string> api_password_;
std::atomic<std::uint16_t> api_port_; std::atomic<std::uint16_t> api_port_;
atomic<std::string> api_user_; utils::atomic<std::string> api_user_;
std::string cache_directory_;
std::atomic<bool> config_changed_; std::atomic<bool> config_changed_;
std::string data_directory_;
std::atomic<database_type> db_type_{database_type::rocksdb}; std::atomic<database_type> db_type_{database_type::rocksdb};
std::atomic<std::uint8_t> download_timeout_secs_; std::atomic<std::uint8_t> download_timeout_secs_;
std::atomic<bool> enable_download_timeout_; std::atomic<bool> enable_download_timeout_;
@@ -87,6 +87,7 @@ private:
std::atomic<std::uint32_t> eviction_delay_mins_; std::atomic<std::uint32_t> eviction_delay_mins_;
std::atomic<bool> eviction_uses_accessed_time_; std::atomic<bool> eviction_uses_accessed_time_;
std::atomic<std::uint16_t> high_freq_interval_secs_; std::atomic<std::uint16_t> high_freq_interval_secs_;
std::string log_directory_;
std::atomic<std::uint16_t> low_freq_interval_secs_; std::atomic<std::uint16_t> low_freq_interval_secs_;
std::atomic<std::uint64_t> max_cache_size_bytes_; std::atomic<std::uint64_t> max_cache_size_bytes_;
std::atomic<std::uint8_t> max_upload_count_; std::atomic<std::uint8_t> max_upload_count_;
@@ -98,20 +99,16 @@ private:
std::atomic<std::uint16_t> task_wait_ms_; std::atomic<std::uint16_t> task_wait_ms_;
private: private:
std::string cache_directory_; utils::atomic<encrypt_config> encrypt_config_;
std::string data_directory_; utils::atomic<host_config> host_config_;
atomic<encrypt_config> encrypt_config_;
atomic<host_config> host_config_;
std::string log_directory_;
mutable std::recursive_mutex read_write_mutex_; mutable std::recursive_mutex read_write_mutex_;
atomic<remote::remote_config> remote_config_; utils::atomic<remote::remote_config> remote_config_;
atomic<remote::remote_mount> remote_mount_; utils::atomic<remote::remote_mount> remote_mount_;
atomic<s3_config> s3_config_; utils::atomic<s3_config> s3_config_;
atomic<sia_config> sia_config_; utils::atomic<sia_config> sia_config_;
std::unordered_map<std::string, std::function<std::string()>> std::unordered_map<std::string, std::function<std::string()>>
value_get_lookup_; value_get_lookup_;
std::unordered_map<std::string, std::unordered_map<std::string, std::function<std::string(std::string_view)>>
std::function<std::string(const std::string &)>>
value_set_lookup_; value_set_lookup_;
std::uint64_t version_{REPERTORY_CONFIG_VERSION}; std::uint64_t version_{REPERTORY_CONFIG_VERSION};
@@ -121,6 +118,8 @@ private:
template <typename dest, typename source> template <typename dest, typename source>
auto set_value(dest &dst, const source &src) -> bool; auto set_value(dest &dst, const source &src) -> bool;
auto set_value(utils::atomic<std::string> &dst, std::string_view src) -> bool;
public: public:
[[nodiscard]] auto get_api_password() const -> std::string; [[nodiscard]] auto get_api_password() const -> std::string;
@@ -190,21 +189,21 @@ public:
[[nodiscard]] auto get_task_wait_ms() const -> std::uint16_t; [[nodiscard]] auto get_task_wait_ms() const -> std::uint16_t;
[[nodiscard]] auto get_value_by_name(const std::string &name) const [[nodiscard]] auto get_value_by_name(std::string_view name) const
-> std::string; -> std::string;
[[nodiscard]] auto get_raw_value_by_name(const std::string &name) const [[nodiscard]] auto get_raw_value_by_name(std::string_view name) const
-> std::string; -> std::string;
[[nodiscard]] auto get_version() const -> std::uint64_t; [[nodiscard]] auto get_version() const -> std::uint64_t;
void save(); void save();
void set_api_password(const std::string &value); void set_api_password(std::string_view value);
void set_api_port(std::uint16_t value); void set_api_port(std::uint16_t value);
void set_api_user(const std::string &value); void set_api_user(std::string_view value);
void set_download_timeout_secs(std::uint8_t value); void set_download_timeout_secs(std::uint8_t value);
@@ -256,8 +255,8 @@ public:
void set_task_wait_ms(std::uint16_t value); void set_task_wait_ms(std::uint16_t value);
[[nodiscard]] auto set_value_by_name(const std::string &name, [[nodiscard]] auto set_value_by_name(std::string_view name,
const std::string &value) -> std::string; std::string_view value) -> std::string;
}; };
} // namespace repertory } // namespace repertory

View File

@@ -43,7 +43,7 @@ private:
using write_callback = size_t (*)(char *, size_t, size_t, void *); using write_callback = size_t (*)(char *, size_t, size_t, void *);
struct read_write_info final { struct read_write_info final {
data_buffer data{}; data_buffer data;
stop_type_callback stop_requested_cb; stop_type_callback stop_requested_cb;
}; };
@@ -62,14 +62,14 @@ public:
public: public:
[[nodiscard]] static auto construct_url(CURL *curl, [[nodiscard]] static auto construct_url(CURL *curl,
const std::string &relative_path, std::string_view relative_path,
const host_config &cfg) const host_config &cfg)
-> std::string; -> std::string;
[[nodiscard]] static auto create_host_config(const s3_config &cfg) [[nodiscard]] static auto create_host_config(const s3_config &cfg)
-> host_config; -> host_config;
[[nodiscard]] static auto url_encode(CURL *curl, const std::string &data, [[nodiscard]] static auto url_encode(CURL *curl, std::string_view data,
bool allow_slash) -> std::string; bool allow_slash) -> std::string;
template <typename request_type> template <typename request_type>
@@ -93,19 +93,19 @@ public:
} }
data_buffer data{}; data_buffer data{};
const auto key = const auto key = utils::encryption::generate_key<utils::hash::hash_256_t>(
utils::encryption::generate_key<utils::encryption::hash_256_t>(
request.decryption_token.value()); request.decryption_token.value());
if (not utils::encryption::read_encrypted_range( if (not utils::encryption::read_encrypted_range(
request.range.value(), key, request.range.value(), key,
[&](data_buffer &ct, std::uint64_t start_offset, [&](data_buffer &buffer, std::uint64_t start_offset,
std::uint64_t end_offset) -> bool { std::uint64_t end_offset) -> bool {
auto encrypted_request = request; auto encrypted_request = request;
encrypted_request.decryption_token = std::nullopt; encrypted_request.decryption_token = std::nullopt;
encrypted_request.range = {{start_offset, end_offset}}; encrypted_request.range = {{start_offset, end_offset}};
encrypted_request.response_handler = encrypted_request.response_handler =
[&ct](const auto &encrypted_data, long /*response_code*/) { [&buffer](const auto &encrypted_data,
ct = encrypted_data; long /*response_code*/) {
buffer = encrypted_data;
}; };
encrypted_request.total_size = std::nullopt; encrypted_request.total_size = std::nullopt;

View File

@@ -23,10 +23,13 @@
#define REPERTORY_INCLUDE_COMM_PACKET_CLIENT_POOL_HPP_ #define REPERTORY_INCLUDE_COMM_PACKET_CLIENT_POOL_HPP_
#include "comm/packet/packet.hpp" #include "comm/packet/packet.hpp"
#include "types/repertory.hpp"
namespace repertory { namespace repertory {
class client_pool final { class client_pool final {
public:
static constexpr const std::uint16_t default_expired_seconds{120U};
static constexpr const std::uint16_t min_expired_seconds{5U};
public: public:
using worker_callback = std::function<packet::error_type()>; using worker_callback = std::function<packet::error_type()>;
using worker_complete_callback = using worker_complete_callback =
@@ -46,15 +49,32 @@ private:
}; };
struct work_queue final { struct work_queue final {
work_queue();
~work_queue();
work_queue(const work_queue &) = delete;
work_queue(work_queue &&) = delete;
std::deque<std::shared_ptr<work_item>> actions;
std::atomic<std::chrono::steady_clock::time_point> modified{
std::chrono::steady_clock::now(),
};
std::mutex mutex; std::mutex mutex;
std::condition_variable notify; std::condition_variable notify;
std::deque<std::shared_ptr<work_item>> queue; stop_type shutdown{false};
std::unique_ptr<std::thread> thread;
auto operator=(const work_queue &) -> work_queue & = delete;
auto operator=(work_queue &&) -> work_queue & = delete;
private:
void work_thread();
}; };
public: public:
explicit pool(std::uint8_t pool_size); pool() noexcept = default;
~pool() { shutdown(); } ~pool();
public: public:
pool(const pool &) = delete; pool(const pool &) = delete;
@@ -63,21 +83,20 @@ private:
auto operator=(pool &&) -> pool & = delete; auto operator=(pool &&) -> pool & = delete;
private: private:
std::vector<std::unique_ptr<work_queue>> pool_queues_; std::mutex pool_mtx_;
std::vector<std::thread> pool_threads_; std::unordered_map<std::uint64_t, std::shared_ptr<work_queue>> pool_queues_;
bool shutdown_{false};
std::atomic<std::uint8_t> thread_index_{};
public: public:
void execute(std::uint64_t thread_id, const worker_callback &worker, void execute(std::uint64_t thread_id, worker_callback worker,
const worker_complete_callback &worker_complete); worker_complete_callback worker_complete);
void remove_expired(std::uint16_t seconds);
void shutdown(); void shutdown();
}; };
public: public:
explicit client_pool(std::uint8_t pool_size = min_pool_size) client_pool() noexcept;
: pool_size_(pool_size == 0U ? min_pool_size : pool_size) {}
~client_pool() { shutdown(); } ~client_pool() { shutdown(); }
@@ -88,20 +107,23 @@ public:
auto operator=(client_pool &&) -> client_pool & = delete; auto operator=(client_pool &&) -> client_pool & = delete;
private: private:
std::uint8_t pool_size_; std::unordered_map<std::string, std::unique_ptr<pool>> pool_lookup_;
std::unordered_map<std::string, std::shared_ptr<pool>> pool_lookup_;
std::mutex pool_mutex_; std::mutex pool_mutex_;
bool shutdown_ = false; stop_type shutdown_{false};
std::atomic<std::uint16_t> expired_seconds_{default_expired_seconds};
private:
static constexpr auto min_pool_size = 10U;
public: public:
void execute(const std::string &client_id, std::uint64_t thread_id, [[nodiscard]] auto get_expired_seconds() const -> std::uint16_t;
const worker_callback &worker,
const worker_complete_callback &worker_complete);
void remove_client(const std::string &client_id); void execute(std::string client_id, std::uint64_t thread_id,
worker_callback worker,
worker_complete_callback worker_complete);
void remove_client(std::string client_id);
void remove_expired();
void set_expired_seconds(std::uint16_t seconds);
void shutdown(); void shutdown();
}; };

View File

@@ -0,0 +1,54 @@
/*
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef REPERTORY_INCLUDE_COMM_PACKET_COMMON_HPP_
#define REPERTORY_INCLUDE_COMM_PACKET_COMMON_HPP_
namespace repertory::comm {
inline static constexpr std::uint32_t max_packet_bytes{32U * 1024U * 1024U};
inline constexpr const std::uint8_t max_read_attempts{2U};
inline constexpr const std::uint16_t packet_nonce_size{256U};
inline constexpr const std::size_t read_write_size{131072U};
inline constexpr const std::uint16_t server_handshake_timeout_ms{3000U};
struct non_blocking_guard final {
non_blocking_guard(const non_blocking_guard &) = delete;
non_blocking_guard(non_blocking_guard &&) = delete;
auto operator=(const non_blocking_guard &) -> non_blocking_guard & = delete;
auto operator=(non_blocking_guard &&) -> non_blocking_guard & = delete;
explicit non_blocking_guard(boost::asio::ip::tcp::socket &sock_);
~non_blocking_guard();
private:
bool non_blocking;
boost::asio::ip::tcp::socket &sock;
};
void apply_common_socket_properties(boost::asio::ip::tcp::socket &sock);
[[nodiscard]] auto is_socket_still_alive(boost::asio::ip::tcp::socket &sock)
-> bool;
} // namespace repertory::comm
#endif // REPERTORY_INCLUDE_COMM_PACKET_COMMON_HPP_

View File

@@ -200,7 +200,7 @@ public:
void encode_top(remote::file_info val); void encode_top(remote::file_info val);
void encrypt(std::string_view token); void encrypt(std::string_view token, bool include_size = true);
[[nodiscard]] auto get_size() const -> std::uint32_t { [[nodiscard]] auto get_size() const -> std::uint32_t {
return static_cast<std::uint32_t>(buffer_.size()); return static_cast<std::uint32_t>(buffer_.size());

View File

@@ -1,17 +1,13 @@
/* /*
Copyright <2018-2025> <scott.e.graves@protonmail.com> Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to do so, subject to the
furnished to do so, subject to the following conditions: following conditions: The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software. THE
The above copyright notice and this permission notice shall be included in all SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
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, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
@@ -24,6 +20,7 @@
#include "comm/packet/packet.hpp" #include "comm/packet/packet.hpp"
#include "types/remote.hpp" #include "types/remote.hpp"
#include "utils/atomic.hpp"
using boost::asio::ip::tcp; using boost::asio::ip::tcp;
@@ -47,43 +44,55 @@ public:
auto operator=(packet_client &&) -> packet_client & = delete; auto operator=(packet_client &&) -> packet_client & = delete;
private: private:
boost::asio::io_context io_context_;
remote::remote_config cfg_; remote::remote_config cfg_;
std::string unique_id_; mutable boost::asio::io_context io_context_;
utils::atomic<std::string> unique_id_;
private: private:
bool allow_connections_{true}; std::atomic<bool> allow_connections_{true};
boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type utils::atomic<
boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type>
resolve_results_; resolve_results_;
std::mutex clients_mutex_; std::mutex clients_mutex_;
std::vector<std::shared_ptr<client>> clients_; std::vector<std::shared_ptr<client>> clients_;
std::vector<std::thread> service_threads_;
private: private:
static void close(client &cli); static void close(client &cli) noexcept;
void close_all(); void close_all();
void connect(client &cli); [[nodiscard]] auto connect(client &cli) -> bool;
[[nodiscard]] auto get_client() -> std::shared_ptr<client>; [[nodiscard]] auto get_client() -> std::shared_ptr<client>;
[[nodiscard]] auto handshake(client &cli, std::uint32_t &min_version) const
-> bool;
void put_client(std::shared_ptr<client> &cli); void put_client(std::shared_ptr<client> &cli);
[[nodiscard]] auto read_packet(client &cli, void read_data(client &cli, data_buffer &buffer) const;
packet &response) const -> packet::error_type;
[[nodiscard]] auto read_packet(client &cli, packet &response) const
-> packet::error_type;
void resolve(); void resolve();
void write_data(client &cli, const packet &request) const;
public: public:
[[nodiscard]] auto send(std::string_view method, [[nodiscard]] auto check_version(std::uint32_t client_version,
std::uint32_t &service_flags) -> packet::error_type; std::uint32_t &min_version) -> api_error;
[[nodiscard]] auto send(std::string_view method, std::uint32_t &service_flags)
-> packet::error_type;
[[nodiscard]] auto send(std::string_view method, packet &request, [[nodiscard]] auto send(std::string_view method, packet &request,
std::uint32_t &service_flags) -> packet::error_type; std::uint32_t &service_flags) -> packet::error_type;
[[nodiscard]] auto send(std::string_view method, packet &request, [[nodiscard]] auto send(std::string_view method, packet &request,
packet &response, packet &response, std::uint32_t &service_flags)
std::uint32_t &service_flags) -> packet::error_type; -> packet::error_type;
}; };
} // namespace repertory } // namespace repertory

View File

@@ -23,6 +23,7 @@
#define REPERTORY_INCLUDE_COMM_PACKET_PACKET_SERVER_HPP_ #define REPERTORY_INCLUDE_COMM_PACKET_PACKET_SERVER_HPP_
#include "comm/packet/client_pool.hpp" #include "comm/packet/client_pool.hpp"
#include "comm/packet/common.hpp"
#include "utils/common.hpp" #include "utils/common.hpp"
using namespace boost::asio; using namespace boost::asio;
@@ -31,10 +32,10 @@ using boost::asio::ip::tcp;
namespace repertory { namespace repertory {
class packet_server final { class packet_server final {
public: public:
using closed_callback = std::function<void(const std::string &)>; using closed_callback = std::function<void(std::string)>;
using message_complete_callback = client_pool::worker_complete_callback; using message_complete_callback = client_pool::worker_complete_callback;
using message_handler_callback = std::function<void( using message_handler_callback =
std::uint32_t, const std::string &, std::uint64_t, const std::string &, std::function<void(std::uint32_t, std::string, std::uint64_t, std::string,
packet *, packet &, message_complete_callback)>; packet *, packet &, message_complete_callback)>;
public: public:
@@ -61,21 +62,25 @@ private:
std::string client_id; std::string client_id;
std::string nonce; std::string nonce;
void generate_nonce() { nonce = utils::generate_random_string(256U); } void generate_nonce() {
nonce = utils::generate_random_string(comm::packet_nonce_size);
}
}; };
private: private:
std::string encryption_token_; std::string encryption_token_;
closed_callback closed_; closed_callback closed_;
message_handler_callback message_handler_; message_handler_callback message_handler_;
io_context io_context_; mutable io_context io_context_;
std::unique_ptr<std::thread> server_thread_; std::unique_ptr<std::thread> server_thread_;
std::vector<std::thread> service_threads_; std::vector<std::thread> service_threads_;
std::recursive_mutex connection_mutex_; std::recursive_mutex connection_mutex_;
std::unordered_map<std::string, std::uint32_t> connection_lookup_; std::unordered_map<std::string, std::uint32_t> connection_lookup_;
private: private:
void add_client(connection &conn, const std::string &client_id); void add_client(connection &conn, std::string client_id);
[[nodiscard]] auto handshake(std::shared_ptr<connection> conn) const -> bool;
void initialize(const uint16_t &port, uint8_t pool_size); void initialize(const uint16_t &port, uint8_t pool_size);

View File

@@ -22,7 +22,7 @@
#ifndef REPERTORY_INCLUDE_COMMON_HPP_ #ifndef REPERTORY_INCLUDE_COMMON_HPP_
#define REPERTORY_INCLUDE_COMMON_HPP_ #define REPERTORY_INCLUDE_COMMON_HPP_
#if defined(__GNUC__) #if defined(__GNUC__) && !defined(PROJECT_IS_DARWIN)
// clang-format off // clang-format off
#define REPERTORY_IGNORE_WARNINGS_ENABLE() \ #define REPERTORY_IGNORE_WARNINGS_ENABLE() \
_Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic push") \
@@ -58,8 +58,8 @@ inline constexpr std::string_view REPERTORY{"repertory"};
inline constexpr std::string_view REPERTORY_DATA_NAME{"repertory2"}; inline constexpr std::string_view REPERTORY_DATA_NAME{"repertory2"};
inline constexpr std::wstring_view REPERTORY_W{L"repertory"}; inline constexpr std::wstring_view REPERTORY_W{L"repertory"};
inline constexpr std::uint64_t REPERTORY_CONFIG_VERSION{2ULL}; inline constexpr std::uint64_t REPERTORY_CONFIG_VERSION{5ULL};
inline constexpr std::string_view REPERTORY_MIN_REMOTE_VERSION{"2.0.0"}; inline constexpr std::string_view REPERTORY_MIN_REMOTE_VERSION{"2.1.0"};
inline constexpr std::string_view RENTERD_MIN_VERSION{"2.0.0"}; inline constexpr std::string_view RENTERD_MIN_VERSION{"2.0.0"};
#define REPERTORY_INVALID_HANDLE INVALID_HANDLE_VALUE #define REPERTORY_INVALID_HANDLE INVALID_HANDLE_VALUE

View File

@@ -29,6 +29,13 @@ class i_file_db {
INTERFACE_SETUP(i_file_db); INTERFACE_SETUP(i_file_db);
public: public:
struct directory_data final {
std::string api_path;
std::pair<utils::encryption::kdf_config, utils::encryption::kdf_config>
kdf_configs;
std::string source_path;
};
struct file_info final { struct file_info final {
std::string api_path; std::string api_path;
bool directory{}; bool directory{};
@@ -40,13 +47,14 @@ public:
std::uint64_t file_size{}; std::uint64_t file_size{};
std::vector< std::vector<
std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>> std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>
iv_list{}; iv_list;
std::pair<utils::encryption::kdf_config, utils::encryption::kdf_config>
kdf_configs;
std::string source_path; std::string source_path;
}; };
public: public:
[[nodiscard]] virtual auto add_directory(const std::string &api_path, [[nodiscard]] virtual auto add_or_update_directory(const directory_data &data)
const std::string &source_path)
-> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto add_or_update_file(const file_data &data) [[nodiscard]] virtual auto add_or_update_file(const file_data &data)
@@ -60,39 +68,43 @@ public:
std::function<void(const std::vector<i_file_db::file_info> &)> callback, std::function<void(const std::vector<i_file_db::file_info> &)> callback,
stop_type_callback stop_requested_cb) const = 0; stop_type_callback stop_requested_cb) const = 0;
[[nodiscard]] virtual auto get_api_path(const std::string &source_path, [[nodiscard]] virtual auto get_api_path(std::string_view source_path,
std::string &api_path) const std::string &api_path) const
-> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
get_directory_api_path(const std::string &source_path, get_directory_api_path(std::string_view source_path,
std::string &api_path) const -> api_error = 0; std::string &api_path) const -> api_error = 0;
[[nodiscard]] virtual auto get_directory_data(std::string_view api_path,
directory_data &data) const
-> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
get_directory_source_path(const std::string &api_path, get_directory_source_path(std::string_view api_path,
std::string &source_path) const -> api_error = 0; std::string &source_path) const -> api_error = 0;
[[nodiscard]] virtual auto get_file_api_path(const std::string &source_path, [[nodiscard]] virtual auto get_file_api_path(std::string_view source_path,
std::string &api_path) const std::string &api_path) const
-> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto get_file_data(const std::string &api_path, [[nodiscard]] virtual auto get_file_data(std::string_view api_path,
file_data &data) const file_data &data) const
-> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
get_file_source_path(const std::string &api_path, get_file_source_path(std::string_view api_path,
std::string &source_path) const -> api_error = 0; std::string &source_path) const -> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
get_item_list(stop_type_callback stop_requested_cb) const get_item_list(stop_type_callback stop_requested_cb) const
-> std::vector<file_info> = 0; -> std::vector<file_info> = 0;
[[nodiscard]] virtual auto get_source_path(const std::string &api_path, [[nodiscard]] virtual auto get_source_path(std::string_view api_path,
std::string &source_path) const std::string &source_path) const
-> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto remove_item(const std::string &api_path) [[nodiscard]] virtual auto remove_item(std::string_view api_path)
-> api_error = 0; -> api_error = 0;
}; };
} // namespace repertory } // namespace repertory

View File

@@ -59,23 +59,23 @@ public:
[[nodiscard]] virtual auto get_resume_list() const [[nodiscard]] virtual auto get_resume_list() const
-> std::vector<resume_entry> = 0; -> std::vector<resume_entry> = 0;
[[nodiscard]] virtual auto get_upload(const std::string &api_path) const [[nodiscard]] virtual auto get_upload(std::string_view api_path) const
-> std::optional<upload_entry> = 0; -> std::optional<upload_entry> = 0;
[[nodiscard]] virtual auto get_upload_active_list() const [[nodiscard]] virtual auto get_upload_active_list() const
-> std::vector<upload_active_entry> = 0; -> std::vector<upload_active_entry> = 0;
[[nodiscard]] virtual auto remove_resume(const std::string &api_path) [[nodiscard]] virtual auto remove_resume(std::string_view api_path)
-> bool = 0; -> bool = 0;
[[nodiscard]] virtual auto remove_upload(const std::string &api_path) [[nodiscard]] virtual auto remove_upload(std::string_view api_path)
-> bool = 0; -> bool = 0;
[[nodiscard]] virtual auto remove_upload_active(const std::string &api_path) [[nodiscard]] virtual auto remove_upload_active(std::string_view api_path)
-> bool = 0; -> bool = 0;
[[nodiscard]] virtual auto rename_resume(const std::string &from_api_path, [[nodiscard]] virtual auto rename_resume(std::string_view from_api_path,
const std::string &to_api_path) std::string_view to_api_path)
-> bool = 0; -> bool = 0;
}; };
} // namespace repertory } // namespace repertory

View File

@@ -35,19 +35,19 @@ public:
std::function<void(const std::vector<std::string> &)> callback, std::function<void(const std::vector<std::string> &)> callback,
stop_type_callback stop_requested_cb) const = 0; stop_type_callback stop_requested_cb) const = 0;
[[nodiscard]] virtual auto get_api_path(const std::string &source_path, [[nodiscard]] virtual auto get_api_path(std::string_view source_path,
std::string &api_path) const std::string &api_path) const
-> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto get_api_path_list() const [[nodiscard]] virtual auto get_api_path_list() const
-> std::vector<std::string> = 0; -> std::vector<std::string> = 0;
[[nodiscard]] virtual auto get_item_meta(const std::string &api_path, [[nodiscard]] virtual auto get_item_meta(std::string_view api_path,
api_meta_map &meta) const api_meta_map &meta) const
-> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto get_item_meta(const std::string &api_path, [[nodiscard]] virtual auto get_item_meta(std::string_view api_path,
const std::string &key, std::string_view key,
std::string &value) const std::string &value) const
-> api_error = 0; -> api_error = 0;
@@ -58,22 +58,22 @@ public:
[[nodiscard]] virtual auto get_total_size() const -> std::uint64_t = 0; [[nodiscard]] virtual auto get_total_size() const -> std::uint64_t = 0;
virtual void remove_api_path(const std::string &api_path) = 0; virtual void remove_api_path(std::string_view api_path) = 0;
[[nodiscard]] virtual auto remove_item_meta(const std::string &api_path, [[nodiscard]] virtual auto remove_item_meta(std::string_view api_path,
const std::string &key) std::string_view key)
-> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto rename_item_meta(const std::string &from_api_path, [[nodiscard]] virtual auto rename_item_meta(std::string_view from_api_path,
const std::string &to_api_path) std::string_view to_api_path)
-> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto set_item_meta(const std::string &api_path, [[nodiscard]] virtual auto set_item_meta(std::string_view api_path,
const std::string &key, std::string_view key,
const std::string &value) std::string_view value)
-> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto set_item_meta(const std::string &api_path, [[nodiscard]] virtual auto set_item_meta(std::string_view api_path,
const api_meta_map &meta) const api_meta_map &meta)
-> api_error = 0; -> api_error = 0;
}; };

View File

@@ -62,13 +62,12 @@ private:
std::function<rocksdb::Status(rocksdb::Transaction *txn)> action) std::function<rocksdb::Status(rocksdb::Transaction *txn)> action)
-> api_error; -> api_error;
[[nodiscard]] auto remove_item(const std::string &api_path, [[nodiscard]] auto remove_item(std::string_view api_path,
const std::string &source_path, std::string_view source_path,
rocksdb::Transaction *txn) -> rocksdb::Status; rocksdb::Transaction *txn) -> rocksdb::Status;
public: public:
[[nodiscard]] auto add_directory(const std::string &api_path, [[nodiscard]] auto add_or_update_directory(const directory_data &data)
const std::string &source_path)
-> api_error override; -> api_error override;
[[nodiscard]] auto add_or_update_file(const i_file_db::file_data &data) [[nodiscard]] auto add_or_update_file(const i_file_db::file_data &data)
@@ -82,38 +81,42 @@ public:
std::function<void(const std::vector<i_file_db::file_info> &)> callback, std::function<void(const std::vector<i_file_db::file_info> &)> callback,
stop_type_callback stop_requested_cb) const override; stop_type_callback stop_requested_cb) const override;
[[nodiscard]] auto get_api_path(const std::string &source_path, [[nodiscard]] auto get_api_path(std::string_view source_path,
std::string &api_path) const std::string &api_path) const
-> api_error override; -> api_error override;
[[nodiscard]] auto get_directory_api_path(const std::string &source_path, [[nodiscard]] auto get_directory_api_path(std::string_view source_path,
std::string &api_path) const std::string &api_path) const
-> api_error override; -> api_error override;
[[nodiscard]] auto get_directory_source_path(const std::string &api_path, [[nodiscard]] auto get_directory_data(std::string_view api_path,
i_file_db::directory_data &data) const
-> api_error override;
[[nodiscard]] auto get_directory_source_path(std::string_view api_path,
std::string &source_path) const std::string &source_path) const
-> api_error override; -> api_error override;
[[nodiscard]] auto get_file_api_path(const std::string &source_path, [[nodiscard]] auto get_file_api_path(std::string_view source_path,
std::string &api_path) const std::string &api_path) const
-> api_error override; -> api_error override;
[[nodiscard]] auto get_file_data(const std::string &api_path, [[nodiscard]] auto get_file_data(std::string_view api_path,
i_file_db::file_data &data) const i_file_db::file_data &data) const
-> api_error override; -> api_error override;
[[nodiscard]] auto get_file_source_path(const std::string &api_path, [[nodiscard]] auto get_file_source_path(std::string_view api_path,
std::string &source_path) const std::string &source_path) const
-> api_error override; -> api_error override;
[[nodiscard]] auto get_item_list(stop_type_callback stop_requested_cb) const [[nodiscard]] auto get_item_list(stop_type_callback stop_requested_cb) const
-> std::vector<i_file_db::file_info> override; -> std::vector<i_file_db::file_info> override;
[[nodiscard]] auto get_source_path(const std::string &api_path, [[nodiscard]] auto get_source_path(std::string_view api_path,
std::string &source_path) const std::string &source_path) const
-> api_error override; -> api_error override;
[[nodiscard]] auto remove_item(const std::string &api_path) [[nodiscard]] auto remove_item(std::string_view api_path)
-> api_error override; -> api_error override;
}; };
} // namespace repertory } // namespace repertory

View File

@@ -61,7 +61,7 @@ private:
std::string_view function_name, std::string_view function_name,
std::function<rocksdb::Status(rocksdb::Transaction *txn)> action) -> bool; std::function<rocksdb::Status(rocksdb::Transaction *txn)> action) -> bool;
[[nodiscard]] auto remove_resume(const std::string &api_path, [[nodiscard]] auto remove_resume(std::string_view api_path,
rocksdb::Transaction *txn) rocksdb::Transaction *txn)
-> rocksdb::Status; -> rocksdb::Status;
@@ -84,23 +84,21 @@ public:
[[nodiscard]] auto get_resume_list() const [[nodiscard]] auto get_resume_list() const
-> std::vector<resume_entry> override; -> std::vector<resume_entry> override;
[[nodiscard]] auto get_upload(const std::string &api_path) const [[nodiscard]] auto get_upload(std::string_view api_path) const
-> std::optional<upload_entry> override; -> std::optional<upload_entry> override;
[[nodiscard]] auto get_upload_active_list() const [[nodiscard]] auto get_upload_active_list() const
-> std::vector<upload_active_entry> override; -> std::vector<upload_active_entry> override;
[[nodiscard]] auto remove_resume(const std::string &api_path) [[nodiscard]] auto remove_resume(std::string_view api_path) -> bool override;
[[nodiscard]] auto remove_upload(std::string_view api_path) -> bool override;
[[nodiscard]] auto remove_upload_active(std::string_view api_path)
-> bool override; -> bool override;
[[nodiscard]] auto remove_upload(const std::string &api_path) [[nodiscard]] auto rename_resume(std::string_view from_api_path,
-> bool override; std::string_view to_api_path)
[[nodiscard]] auto remove_upload_active(const std::string &api_path)
-> bool override;
[[nodiscard]] auto rename_resume(const std::string &from_api_path,
const std::string &to_api_path)
-> bool override; -> bool override;
}; };

View File

@@ -54,7 +54,7 @@ private:
void create_or_open(bool clear); void create_or_open(bool clear);
[[nodiscard]] auto get_item_meta_json(const std::string &api_path, [[nodiscard]] auto get_item_meta_json(std::string_view api_path,
json &json_data) const -> api_error; json &json_data) const -> api_error;
[[nodiscard]] static auto [[nodiscard]] static auto
@@ -66,13 +66,12 @@ private:
std::function<rocksdb::Status(rocksdb::Transaction *txn)> action) std::function<rocksdb::Status(rocksdb::Transaction *txn)> action)
-> api_error; -> api_error;
[[nodiscard]] auto remove_api_path(const std::string &api_path, [[nodiscard]] auto remove_api_path(std::string_view api_path,
const std::string &source_path, std::string_view source_path,
rocksdb::Transaction *txn) rocksdb::Transaction *txn)
-> rocksdb::Status; -> rocksdb::Status;
[[nodiscard]] auto update_item_meta(const std::string &api_path, [[nodiscard]] auto update_item_meta(std::string_view api_path, json json_data,
json json_data,
rocksdb::Transaction *base_txn = nullptr, rocksdb::Transaction *base_txn = nullptr,
rocksdb::Status *status = nullptr) rocksdb::Status *status = nullptr)
-> api_error; -> api_error;
@@ -84,19 +83,19 @@ public:
std::function<void(const std::vector<std::string> &)> callback, std::function<void(const std::vector<std::string> &)> callback,
stop_type_callback stop_requested_cb) const override; stop_type_callback stop_requested_cb) const override;
[[nodiscard]] auto get_api_path(const std::string &source_path, [[nodiscard]] auto get_api_path(std::string_view source_path,
std::string &api_path) const std::string &api_path) const
-> api_error override; -> api_error override;
[[nodiscard]] auto get_api_path_list() const [[nodiscard]] auto get_api_path_list() const
-> std::vector<std::string> override; -> std::vector<std::string> override;
[[nodiscard]] auto get_item_meta(const std::string &api_path, [[nodiscard]] auto get_item_meta(std::string_view api_path,
api_meta_map &meta) const api_meta_map &meta) const
-> api_error override; -> api_error override;
[[nodiscard]] auto get_item_meta(const std::string &api_path, [[nodiscard]] auto get_item_meta(std::string_view api_path,
const std::string &key, std::string_view key,
std::string &value) const std::string &value) const
-> api_error override; -> api_error override;
@@ -107,22 +106,21 @@ public:
[[nodiscard]] auto get_total_size() const -> std::uint64_t override; [[nodiscard]] auto get_total_size() const -> std::uint64_t override;
void remove_api_path(const std::string &api_path) override; void remove_api_path(std::string_view api_path) override;
[[nodiscard]] auto remove_item_meta(const std::string &api_path, [[nodiscard]] auto remove_item_meta(std::string_view api_path,
const std::string &key) std::string_view key)
-> api_error override; -> api_error override;
[[nodiscard]] auto rename_item_meta(const std::string &from_api_path, [[nodiscard]] auto rename_item_meta(std::string_view from_api_path,
const std::string &to_api_path) std::string_view to_api_path)
-> api_error override; -> api_error override;
[[nodiscard]] auto set_item_meta(const std::string &api_path, [[nodiscard]] auto set_item_meta(std::string_view api_path,
const std::string &key, std::string_view key, std::string_view value)
const std::string &value)
-> api_error override; -> api_error override;
[[nodiscard]] auto set_item_meta(const std::string &api_path, [[nodiscard]] auto set_item_meta(std::string_view api_path,
const api_meta_map &meta) const api_meta_map &meta)
-> api_error override; -> api_error override;
}; };

View File

@@ -42,8 +42,8 @@ private:
utils::db::sqlite::db3_t db_; utils::db::sqlite::db3_t db_;
public: public:
[[nodiscard]] auto add_directory(const std::string &api_path, [[nodiscard]] auto
const std::string &source_path) add_or_update_directory(const i_file_db::directory_data &data)
-> api_error override; -> api_error override;
[[nodiscard]] auto add_or_update_file(const i_file_db::file_data &data) [[nodiscard]] auto add_or_update_file(const i_file_db::file_data &data)
@@ -57,38 +57,42 @@ public:
std::function<void(const std::vector<i_file_db::file_info> &)> callback, std::function<void(const std::vector<i_file_db::file_info> &)> callback,
stop_type_callback stop_requested_cb) const override; stop_type_callback stop_requested_cb) const override;
[[nodiscard]] auto get_api_path(const std::string &source_path, [[nodiscard]] auto get_api_path(std::string_view source_path,
std::string &api_path) const std::string &api_path) const
-> api_error override; -> api_error override;
[[nodiscard]] auto get_directory_api_path(const std::string &source_path, [[nodiscard]] auto get_directory_api_path(std::string_view source_path,
std::string &api_path) const std::string &api_path) const
-> api_error override; -> api_error override;
[[nodiscard]] auto get_directory_source_path(const std::string &api_path, [[nodiscard]] auto get_directory_data(std::string_view api_path,
i_file_db::directory_data &data) const
-> api_error override;
[[nodiscard]] auto get_directory_source_path(std::string_view api_path,
std::string &source_path) const std::string &source_path) const
-> api_error override; -> api_error override;
[[nodiscard]] auto get_file_api_path(const std::string &source_path, [[nodiscard]] auto get_file_api_path(std::string_view source_path,
std::string &api_path) const std::string &api_path) const
-> api_error override; -> api_error override;
[[nodiscard]] auto get_file_data(const std::string &api_path, [[nodiscard]] auto get_file_data(std::string_view api_path,
i_file_db::file_data &data) const i_file_db::file_data &data) const
-> api_error override; -> api_error override;
[[nodiscard]] auto get_file_source_path(const std::string &api_path, [[nodiscard]] auto get_file_source_path(std::string_view api_path,
std::string &source_path) const std::string &source_path) const
-> api_error override; -> api_error override;
[[nodiscard]] auto get_item_list(stop_type_callback stop_requested_cb) const [[nodiscard]] auto get_item_list(stop_type_callback stop_requested_cb) const
-> std::vector<i_file_db::file_info> override; -> std::vector<i_file_db::file_info> override;
[[nodiscard]] auto get_source_path(const std::string &api_path, [[nodiscard]] auto get_source_path(std::string_view api_path,
std::string &source_path) const std::string &source_path) const
-> api_error override; -> api_error override;
[[nodiscard]] auto remove_item(const std::string &api_path) [[nodiscard]] auto remove_item(std::string_view api_path)
-> api_error override; -> api_error override;
}; };
} // namespace repertory } // namespace repertory

View File

@@ -57,23 +57,21 @@ public:
[[nodiscard]] auto get_resume_list() const [[nodiscard]] auto get_resume_list() const
-> std::vector<resume_entry> override; -> std::vector<resume_entry> override;
[[nodiscard]] auto get_upload(const std::string &api_path) const [[nodiscard]] auto get_upload(std::string_view api_path) const
-> std::optional<upload_entry> override; -> std::optional<upload_entry> override;
[[nodiscard]] auto get_upload_active_list() const [[nodiscard]] auto get_upload_active_list() const
-> std::vector<upload_active_entry> override; -> std::vector<upload_active_entry> override;
[[nodiscard]] auto remove_resume(const std::string &api_path) [[nodiscard]] auto remove_resume(std::string_view api_path) -> bool override;
[[nodiscard]] auto remove_upload(std::string_view api_path) -> bool override;
[[nodiscard]] auto remove_upload_active(std::string_view api_path)
-> bool override; -> bool override;
[[nodiscard]] auto remove_upload(const std::string &api_path) [[nodiscard]] auto rename_resume(std::string_view from_api_path,
-> bool override; std::string_view to_api_path)
[[nodiscard]] auto remove_upload_active(const std::string &api_path)
-> bool override;
[[nodiscard]] auto rename_resume(const std::string &from_api_path,
const std::string &to_api_path)
-> bool override; -> bool override;
}; };

View File

@@ -44,7 +44,7 @@ private:
constexpr static const auto table_name = "meta"; constexpr static const auto table_name = "meta";
private: private:
[[nodiscard]] auto update_item_meta(const std::string &api_path, [[nodiscard]] auto update_item_meta(std::string_view api_path,
api_meta_map meta) -> api_error; api_meta_map meta) -> api_error;
public: public:
@@ -54,19 +54,19 @@ public:
std::function<void(const std::vector<std::string> &)> callback, std::function<void(const std::vector<std::string> &)> callback,
stop_type_callback stop_requested_cb) const override; stop_type_callback stop_requested_cb) const override;
[[nodiscard]] auto get_api_path(const std::string &source_path, [[nodiscard]] auto get_api_path(std::string_view source_path,
std::string &api_path) const std::string &api_path) const
-> api_error override; -> api_error override;
[[nodiscard]] auto get_api_path_list() const [[nodiscard]] auto get_api_path_list() const
-> std::vector<std::string> override; -> std::vector<std::string> override;
[[nodiscard]] auto get_item_meta(const std::string &api_path, [[nodiscard]] auto get_item_meta(std::string_view api_path,
api_meta_map &meta) const api_meta_map &meta) const
-> api_error override; -> api_error override;
[[nodiscard]] auto get_item_meta(const std::string &api_path, [[nodiscard]] auto get_item_meta(std::string_view api_path,
const std::string &key, std::string_view key,
std::string &value) const std::string &value) const
-> api_error override; -> api_error override;
@@ -77,22 +77,21 @@ public:
[[nodiscard]] auto get_total_size() const -> std::uint64_t override; [[nodiscard]] auto get_total_size() const -> std::uint64_t override;
void remove_api_path(const std::string &api_path) override; void remove_api_path(std::string_view api_path) override;
[[nodiscard]] auto remove_item_meta(const std::string &api_path, [[nodiscard]] auto remove_item_meta(std::string_view api_path,
const std::string &key) std::string_view key)
-> api_error override; -> api_error override;
[[nodiscard]] auto rename_item_meta(const std::string &from_api_path, [[nodiscard]] auto rename_item_meta(std::string_view from_api_path,
const std::string &to_api_path) std::string_view to_api_path)
-> api_error override; -> api_error override;
[[nodiscard]] auto set_item_meta(const std::string &api_path, [[nodiscard]] auto set_item_meta(std::string_view api_path,
const std::string &key, std::string_view key, std::string_view value)
const std::string &value)
-> api_error override; -> api_error override;
[[nodiscard]] auto set_item_meta(const std::string &api_path, [[nodiscard]] auto set_item_meta(std::string_view api_path,
const api_meta_map &meta) const api_meta_map &meta)
-> api_error override; -> api_error override;
}; };

View File

@@ -49,18 +49,18 @@ private:
std::recursive_mutex directory_mutex_; std::recursive_mutex directory_mutex_;
public: public:
void execute_action(const std::string &api_path, void execute_action(std::string_view api_path,
const execute_callback &execute); const execute_callback &execute);
[[nodiscard]] auto get_directory(std::uint64_t handle) [[nodiscard]] auto get_directory(std::uint64_t handle)
-> std::shared_ptr<directory_iterator>; -> std::shared_ptr<directory_iterator>;
auto remove_directory(const std::string &api_path) auto remove_directory(std::string_view api_path)
-> std::shared_ptr<directory_iterator>; -> std::shared_ptr<directory_iterator>;
void remove_directory(std::uint64_t handle); void remove_directory(std::uint64_t handle);
void set_directory(const std::string &api_path, std::uint64_t handle, void set_directory(std::string_view api_path, std::uint64_t handle,
std::shared_ptr<directory_iterator> iterator); std::shared_ptr<directory_iterator> iterator);
}; };
} // namespace repertory } // namespace repertory

View File

@@ -30,8 +30,8 @@ class directory_iterator final {
public: public:
#if !defined(_WIN32) #if !defined(_WIN32)
using populate_stat_callback = using populate_stat_callback =
std::function<void(const std::string &, std::uint64_t, std::function<void(std::string_view, std::uint64_t, const api_meta_map &,
const api_meta_map &, bool, struct stat *)>; bool, struct stat *)>;
#endif #endif
public: public:
explicit directory_iterator(directory_item_list list) explicit directory_iterator(directory_item_list list)
@@ -47,7 +47,7 @@ private:
public: public:
#if !defined(_WIN32) #if !defined(_WIN32)
[[nodiscard]] auto fill_buffer(const remote::file_offset &offset, [[nodiscard]] auto fill_buffer(remote::file_offset offset,
fuse_fill_dir_t filler_function, void *buffer, fuse_fill_dir_t filler_function, void *buffer,
populate_stat_callback populate_stat) -> int; populate_stat_callback populate_stat) -> int;
#endif // !defined(_WIN32) #endif // !defined(_WIN32)
@@ -59,13 +59,13 @@ public:
[[nodiscard]] auto get_directory_item(std::size_t offset, directory_item &di) [[nodiscard]] auto get_directory_item(std::size_t offset, directory_item &di)
-> api_error; -> api_error;
[[nodiscard]] auto get_directory_item(const std::string &api_path, [[nodiscard]] auto get_directory_item(std::string_view api_path,
directory_item &di) -> api_error; directory_item &di) -> api_error;
[[nodiscard]] auto get_json(std::size_t offset, json &item) -> int; [[nodiscard]] auto get_json(std::size_t offset, json &item) -> int;
[[nodiscard]] auto [[nodiscard]] auto get_next_directory_offset(std::string_view api_path) const
get_next_directory_offset(const std::string &api_path) const -> std::size_t; -> std::size_t;
public: public:
auto operator=(const directory_iterator &iterator) noexcept auto operator=(const directory_iterator &iterator) noexcept

View File

@@ -46,7 +46,7 @@ private:
i_provider &provider_; i_provider &provider_;
private: private:
[[nodiscard]] auto check_minimum_requirements(const std::string &file_path) [[nodiscard]] auto check_minimum_requirements(std::string_view file_path)
-> bool; -> bool;
[[nodiscard]] auto get_filtered_cached_files() -> std::deque<std::string>; [[nodiscard]] auto get_filtered_cached_files() -> std::deque<std::string>;

View File

@@ -52,7 +52,11 @@ private:
protected: protected:
bool atime_enabled_{true}; bool atime_enabled_{true};
bool console_enabled_{false}; bool console_enabled_{true};
bool foreground_{false};
#if defined(__APPLE__)
std::string label_;
#endif // defined(__APPLE__)
std::optional<gid_t> forced_gid_; std::optional<gid_t> forced_gid_;
std::optional<uid_t> forced_uid_; std::optional<uid_t> forced_uid_;
std::optional<mode_t> forced_umask_; std::optional<mode_t> forced_umask_;
@@ -95,50 +99,51 @@ private:
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
[[nodiscard]] static auto chmod_(const char *path, mode_t mode, [[nodiscard]] static auto chmod_(const char *path, mode_t mode,
struct fuse_file_info *fi) -> int; struct fuse_file_info *f_info) -> int;
#else // FUSE_USE_VERSION < 30 #else // FUSE_USE_VERSION < 30
[[nodiscard]] static auto chmod_(const char *path, mode_t mode) -> int; [[nodiscard]] static auto chmod_(const char *path, mode_t mode) -> int;
#endif // FUSE_USE_VERSION >= 30 #endif // FUSE_USE_VERSION >= 30
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
[[nodiscard]] static auto chown_(const char *path, uid_t uid, gid_t gid, [[nodiscard]] static auto chown_(const char *path, uid_t uid, gid_t gid,
struct fuse_file_info *fi) -> int; struct fuse_file_info *f_info) -> int;
#else // FUSE_USE_VERSION < 30 #else // FUSE_USE_VERSION < 30
[[nodiscard]] static auto chown_(const char *path, uid_t uid, gid_t gid) [[nodiscard]] static auto chown_(const char *path, uid_t uid, gid_t gid)
-> int; -> int;
#endif // FUSE_USE_VERSION >= 30 #endif // FUSE_USE_VERSION >= 30
[[nodiscard]] static auto create_(const char *path, mode_t mode, [[nodiscard]] static auto create_(const char *path, mode_t mode,
struct fuse_file_info *fi) -> int; struct fuse_file_info *f_info) -> int;
static void destroy_(void *ptr); static void destroy_(void *ptr);
[[nodiscard]] static auto fallocate_(const char *path, int mode, off_t offset, [[nodiscard]] static auto fallocate_(const char *path, int mode, off_t offset,
off_t length, struct fuse_file_info *fi) off_t length,
-> int; struct fuse_file_info *f_info) -> int;
#if FUSE_USE_VERSION < 30 #if FUSE_USE_VERSION < 30
[[nodiscard]] static auto fgetattr_(const char *path, struct stat *st, [[nodiscard]] static auto fgetattr_(const char *path, struct stat *u_stat,
struct fuse_file_info *fi) -> int; struct fuse_file_info *f_info) -> int;
#endif // FUSE_USE_VERSION < 30 #endif // FUSE_USE_VERSION < 30
#if defined(__APPLE__) #if defined(__APPLE__)
[[nodiscard]] static auto fsetattr_x_(const char *path, [[nodiscard]] static auto fsetattr_x_(const char *path,
struct setattr_x *attr, struct setattr_x *attr,
struct fuse_file_info *fi) -> int; struct fuse_file_info *f_info) -> int;
#endif // defined(__APPLE__) #endif // defined(__APPLE__)
[[nodiscard]] static auto fsync_(const char *path, int datasync, [[nodiscard]] static auto fsync_(const char *path, int datasync,
struct fuse_file_info *fi) -> int; struct fuse_file_info *f_info) -> int;
[[nodiscard]] static auto ftruncate_(const char *path, off_t size, [[nodiscard]] static auto ftruncate_(const char *path, off_t size,
struct fuse_file_info *fi) -> int; struct fuse_file_info *f_info) -> int;
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
[[nodiscard]] static auto getattr_(const char *path, struct stat *st, [[nodiscard]] static auto getattr_(const char *path, struct stat *u_stat,
struct fuse_file_info *fi) -> int; struct fuse_file_info *f_info) -> int;
#else // FUSE_USE_VERSION < 30 #else // FUSE_USE_VERSION < 30
[[nodiscard]] static auto getattr_(const char *path, struct stat *st) -> int; [[nodiscard]] static auto getattr_(const char *path, struct stat *u_stat)
-> int;
#endif // FUSE_USE_VERSION >= 30 #endif // FUSE_USE_VERSION >= 30
#if defined(__APPLE__) #if defined(__APPLE__)
@@ -154,35 +159,40 @@ private:
[[nodiscard]] static auto init_(struct fuse_conn_info *conn) -> void *; [[nodiscard]] static auto init_(struct fuse_conn_info *conn) -> void *;
#endif // FUSE_USE_VERSION >= 30 #endif // FUSE_USE_VERSION >= 30
[[nodiscard]] static auto ioctl_(const char *path, int cmd, void *arg,
struct fuse_file_info *f_info,
unsigned int flags, void *data) -> int;
[[nodiscard]] static auto mkdir_(const char *path, mode_t mode) -> int; [[nodiscard]] static auto mkdir_(const char *path, mode_t mode) -> int;
[[nodiscard]] static auto open_(const char *path, struct fuse_file_info *fi) [[nodiscard]] static auto open_(const char *path,
-> int; struct fuse_file_info *f_info) -> int;
[[nodiscard]] static auto opendir_(const char *path, [[nodiscard]] static auto opendir_(const char *path,
struct fuse_file_info *fi) -> int; struct fuse_file_info *f_info) -> int;
[[nodiscard]] static auto read_(const char *path, char *buffer, [[nodiscard]] static auto read_(const char *path, char *buffer,
size_t read_size, off_t read_offset, size_t read_size, off_t read_offset,
struct fuse_file_info *fi) -> int; struct fuse_file_info *f_info) -> int;
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
[[nodiscard]] static auto readdir_(const char *path, void *buf, [[nodiscard]] static auto readdir_(const char *path, void *buf,
fuse_fill_dir_t fuse_fill_dir, fuse_fill_dir_t fuse_fill_dir,
off_t offset, struct fuse_file_info *fi, off_t offset,
struct fuse_file_info *f_info,
fuse_readdir_flags flags) -> int; fuse_readdir_flags flags) -> int;
#else // FUSE_USE_VERSION < 30 #else // FUSE_USE_VERSION < 30
[[nodiscard]] static auto readdir_(const char *path, void *buf, [[nodiscard]] static auto readdir_(const char *path, void *buf,
fuse_fill_dir_t fuse_fill_dir, fuse_fill_dir_t fuse_fill_dir,
off_t offset, struct fuse_file_info *fi) off_t offset,
-> int; struct fuse_file_info *f_info) -> int;
#endif // FUSE_USE_VERSION >= 30 #endif // FUSE_USE_VERSION >= 30
[[nodiscard]] static auto release_(const char *path, [[nodiscard]] static auto release_(const char *path,
struct fuse_file_info *fi) -> int; struct fuse_file_info *f_info) -> int;
[[nodiscard]] static auto releasedir_(const char *path, [[nodiscard]] static auto releasedir_(const char *path,
struct fuse_file_info *fi) -> int; struct fuse_file_info *f_info) -> int;
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
[[nodiscard]] static auto rename_(const char *from, const char *to, [[nodiscard]] static auto rename_(const char *from, const char *to,
@@ -248,7 +258,7 @@ private:
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
[[nodiscard]] static auto truncate_(const char *path, off_t size, [[nodiscard]] static auto truncate_(const char *path, off_t size,
struct fuse_file_info *fi) -> int; struct fuse_file_info *f_info) -> int;
#else // FUSE_USE_VERSION < 30 #else // FUSE_USE_VERSION < 30
[[nodiscard]] static auto truncate_(const char *path, off_t size) -> int; [[nodiscard]] static auto truncate_(const char *path, off_t size) -> int;
#endif // FUSE_USE_VERSION >= 30 #endif // FUSE_USE_VERSION >= 30
@@ -258,7 +268,7 @@ private:
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
[[nodiscard]] static auto utimens_(const char *path, [[nodiscard]] static auto utimens_(const char *path,
const struct timespec tv[2], const struct timespec tv[2],
struct fuse_file_info *fi) -> int; struct fuse_file_info *f_info) -> int;
#else // FUSE_USE_VERSION < 30 #else // FUSE_USE_VERSION < 30
[[nodiscard]] static auto utimens_(const char *path, [[nodiscard]] static auto utimens_(const char *path,
const struct timespec tv[2]) -> int; const struct timespec tv[2]) -> int;
@@ -266,7 +276,7 @@ private:
[[nodiscard]] static auto write_(const char *path, const char *buffer, [[nodiscard]] static auto write_(const char *path, const char *buffer,
size_t write_size, off_t write_offset, size_t write_size, off_t write_offset,
struct fuse_file_info *fi) -> int; struct fuse_file_info *f_info) -> int;
protected: protected:
[[nodiscard]] virtual auto access_impl(std::string /*api_path*/, int /*mask*/) [[nodiscard]] virtual auto access_impl(std::string /*api_path*/, int /*mask*/)
@@ -284,11 +294,11 @@ protected:
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
[[nodiscard]] virtual auto chmod_impl(std::string /*api_path*/, [[nodiscard]] virtual auto chmod_impl(std::string /*api_path*/,
mode_t /*mode*/, mode_t /*mode*/,
struct fuse_file_info * /*fi*/) struct fuse_file_info * /*f_info*/)
-> api_error { -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
#else //FUSE_USE_VERSION < 30 #else // FUSE_USE_VERSION < 30
[[nodiscard]] virtual auto chmod_impl(std::string /*api_path*/, [[nodiscard]] virtual auto chmod_impl(std::string /*api_path*/,
mode_t /*mode*/) -> api_error { mode_t /*mode*/) -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
@@ -298,7 +308,7 @@ protected:
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
[[nodiscard]] virtual auto chown_impl(std::string /*api_path*/, uid_t /*uid*/, [[nodiscard]] virtual auto chown_impl(std::string /*api_path*/, uid_t /*uid*/,
gid_t /*gid*/, gid_t /*gid*/,
struct fuse_file_info * /*fi*/) struct fuse_file_info * /*f_info*/)
-> api_error { -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
@@ -311,7 +321,7 @@ protected:
[[nodiscard]] virtual auto create_impl(std::string /*api_path*/, [[nodiscard]] virtual auto create_impl(std::string /*api_path*/,
mode_t /*mode*/, mode_t /*mode*/,
struct fuse_file_info * /*fi*/) struct fuse_file_info * /*f_info*/)
-> api_error { -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
@@ -320,14 +330,14 @@ protected:
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
fallocate_impl(std::string /*api_path*/, int /*mode*/, off_t /*offset*/, fallocate_impl(std::string /*api_path*/, int /*mode*/, off_t /*offset*/,
off_t /*length*/, struct fuse_file_info * /*fi*/) off_t /*length*/, struct fuse_file_info * /*f_info*/)
-> api_error { -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
[[nodiscard]] virtual auto fgetattr_impl(std::string /*api_path*/, [[nodiscard]] virtual auto fgetattr_impl(std::string /*api_path*/,
struct stat * /*st*/, struct stat * /*u_stat*/,
struct fuse_file_info * /*fi*/) struct fuse_file_info * /*f_info*/)
-> api_error { -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
@@ -335,7 +345,7 @@ protected:
#if defined(__APPLE__) #if defined(__APPLE__)
[[nodiscard]] virtual auto fsetattr_x_impl(std::string /*api_path*/, [[nodiscard]] virtual auto fsetattr_x_impl(std::string /*api_path*/,
struct setattr_x * /*attr*/, struct setattr_x * /*attr*/,
struct fuse_file_info * /*fi*/) struct fuse_file_info * /*f_info*/)
-> api_error { -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
@@ -343,7 +353,7 @@ protected:
[[nodiscard]] virtual auto fsync_impl(std::string /*api_path*/, [[nodiscard]] virtual auto fsync_impl(std::string /*api_path*/,
int /*datasync*/, int /*datasync*/,
struct fuse_file_info * /*fi*/) struct fuse_file_info * /*f_info*/)
-> api_error { -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
@@ -351,7 +361,7 @@ protected:
#if FUSE_USE_VERSION < 30 #if FUSE_USE_VERSION < 30
[[nodiscard]] virtual auto ftruncate_impl(std::string /*api_path*/, [[nodiscard]] virtual auto ftruncate_impl(std::string /*api_path*/,
off_t /*size*/, off_t /*size*/,
struct fuse_file_info * /*fi*/) struct fuse_file_info * /*f_info*/)
-> api_error { -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
@@ -359,14 +369,15 @@ protected:
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
[[nodiscard]] virtual auto getattr_impl(std::string /*api_path*/, [[nodiscard]] virtual auto getattr_impl(std::string /*api_path*/,
struct stat * /*st*/, struct stat * /*u_stat*/,
struct fuse_file_info * /*fi*/) struct fuse_file_info * /*f_info*/)
-> api_error { -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
#else // FUSE_USE_VERSION < 30 #else // FUSE_USE_VERSION < 30
[[nodiscard]] virtual auto getattr_impl(std::string /*api_path*/, [[nodiscard]] virtual auto getattr_impl(std::string /*api_path*/,
struct stat * /*st*/) -> api_error { struct stat * /*u_stat*/)
-> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
#endif // FUSE_USE_VERSION >= 30 #endif // FUSE_USE_VERSION >= 30
@@ -387,26 +398,33 @@ protected:
virtual auto init_impl(struct fuse_conn_info *conn) -> void *; virtual auto init_impl(struct fuse_conn_info *conn) -> void *;
#endif // FUSE_USE_VERSION >= 30 #endif // FUSE_USE_VERSION >= 30
[[nodiscard]] virtual auto ioctl_impl(std::string /*api_path*/, int /* cmd */,
void * /* arg */,
struct fuse_file_info * /*f_info*/)
-> api_error {
return api_error::no_tty;
}
[[nodiscard]] virtual auto mkdir_impl(std::string /*api_path*/, [[nodiscard]] virtual auto mkdir_impl(std::string /*api_path*/,
mode_t /*mode*/) -> api_error { mode_t /*mode*/) -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
[[nodiscard]] virtual auto open_impl(std::string /*api_path*/, [[nodiscard]] virtual auto open_impl(std::string /*api_path*/,
struct fuse_file_info * /*fi*/) struct fuse_file_info * /*f_info*/)
-> api_error { -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
[[nodiscard]] virtual auto opendir_impl(std::string /*api_path*/, [[nodiscard]] virtual auto opendir_impl(std::string /*api_path*/,
struct fuse_file_info * /*fi*/) struct fuse_file_info * /*f_info*/)
-> api_error { -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
read_impl(std::string /*api_path*/, char * /*buffer*/, size_t /*read_size*/, 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 * /*f_info*/,
std::size_t & /*bytes_read*/) -> api_error { std::size_t & /*bytes_read*/) -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
@@ -415,7 +433,7 @@ protected:
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
readdir_impl(std::string /*api_path*/, void * /*buf*/, readdir_impl(std::string /*api_path*/, void * /*buf*/,
fuse_fill_dir_t /*fuse_fill_dir*/, off_t /*offset*/, fuse_fill_dir_t /*fuse_fill_dir*/, off_t /*offset*/,
struct fuse_file_info * /*fi*/, fuse_readdir_flags /*flags*/) struct fuse_file_info * /*f_info*/, fuse_readdir_flags /*flags*/)
-> api_error { -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
@@ -423,19 +441,19 @@ protected:
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
readdir_impl(std::string /*api_path*/, void * /*buf*/, readdir_impl(std::string /*api_path*/, void * /*buf*/,
fuse_fill_dir_t /*fuse_fill_dir*/, off_t /*offset*/, fuse_fill_dir_t /*fuse_fill_dir*/, off_t /*offset*/,
struct fuse_file_info * /*fi*/) -> api_error { struct fuse_file_info * /*f_info*/) -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
#endif // FUSE_USE_VERSION >= 30 #endif // FUSE_USE_VERSION >= 30
[[nodiscard]] virtual auto release_impl(std::string /*api_path*/, [[nodiscard]] virtual auto release_impl(std::string /*api_path*/,
struct fuse_file_info * /*fi*/) struct fuse_file_info * /*f_info*/)
-> api_error { -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
[[nodiscard]] virtual auto releasedir_impl(std::string /*api_path*/, [[nodiscard]] virtual auto releasedir_impl(std::string /*api_path*/,
struct fuse_file_info * /*fi*/) struct fuse_file_info * /*f_info*/)
-> api_error { -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
@@ -464,14 +482,14 @@ protected:
getxattr_impl(std::string /*api_path*/, const char * /*name*/, getxattr_impl(std::string /*api_path*/, const char * /*name*/,
char * /*value*/, size_t /*size*/, uint32_t /*position*/, char * /*value*/, size_t /*size*/, uint32_t /*position*/,
int & /*attribute_size*/) -> api_error { int & /*attribute_size*/) -> api_error {
return api_error::not_implemented; return api_error::xattr_not_found;
} }
#else // !defined(__APPLE__) #else // !defined(__APPLE__)
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
getxattr_impl(std::string /*api_path*/, const char * /*name*/, getxattr_impl(std::string /*api_path*/, const char * /*name*/,
char * /*value*/, size_t /*size*/, int & /*attribute_size*/) char * /*value*/, size_t /*size*/, int & /*attribute_size*/)
-> api_error { -> api_error {
return api_error::not_implemented; return api_error::xattr_not_found;
} }
#endif // defined(__APPLE__) #endif // defined(__APPLE__)
@@ -551,7 +569,7 @@ protected:
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
[[nodiscard]] virtual auto truncate_impl(std::string /*api_path*/, [[nodiscard]] virtual auto truncate_impl(std::string /*api_path*/,
off_t /*size*/, off_t /*size*/,
struct fuse_file_info * /*fi*/) struct fuse_file_info * /*f_info*/)
-> api_error { -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
@@ -570,7 +588,7 @@ protected:
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
[[nodiscard]] virtual auto utimens_impl(std::string /*api_path*/, [[nodiscard]] virtual auto utimens_impl(std::string /*api_path*/,
const struct timespec /*tv*/[2], const struct timespec /*tv*/[2],
struct fuse_file_info * /*fi*/) struct fuse_file_info * /*f_info*/)
-> api_error { -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
@@ -585,8 +603,8 @@ protected:
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
write_impl(std::string /*api_path*/, const char * /*buffer*/, write_impl(std::string /*api_path*/, const char * /*buffer*/,
size_t /*write_size*/, off_t /*write_offset*/, size_t /*write_size*/, off_t /*write_offset*/,
struct fuse_file_info * /*fi*/, std::size_t & /*bytes_written*/) struct fuse_file_info * /*f_info*/,
-> api_error { std::size_t & /*bytes_written*/) -> api_error {
return api_error::not_implemented; return api_error::not_implemented;
} }
@@ -604,13 +622,15 @@ public:
static void display_version_information(std::vector<const char *> args); static void display_version_information(std::vector<const char *> args);
static auto unmount(const std::string &mount_location) -> int; auto unmount(std::string_view mount_location) -> int;
[[nodiscard]] auto get_mount_location() const -> std::string { [[nodiscard]] auto get_mount_location() const -> std::string {
return mount_location_; return mount_location_;
} }
[[nodiscard]] auto mount(std::vector<std::string> args) -> int; [[nodiscard]] auto mount(std::vector<std::string> orig_args,
std::vector<std::string> args, provider_type prov,
std::string_view unique_id) -> int;
}; };
} // namespace repertory } // namespace repertory

View File

@@ -67,7 +67,7 @@ private:
bool was_mounted_{false}; bool was_mounted_{false};
private: private:
void update_accessed_time(const std::string &api_path); void update_accessed_time(std::string_view api_path);
void stop_all(); void stop_all();
@@ -79,7 +79,7 @@ protected:
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
[[nodiscard]] auto chmod_impl(std::string api_path, mode_t mode, [[nodiscard]] auto chmod_impl(std::string api_path, mode_t mode,
struct fuse_file_info *file_info) struct fuse_file_info *f_info)
-> api_error override; -> api_error override;
#else // FUSE_USE_VERSION < 30 #else // FUSE_USE_VERSION < 30
[[nodiscard]] auto chmod_impl(std::string api_path, mode_t mode) [[nodiscard]] auto chmod_impl(std::string api_path, mode_t mode)
@@ -88,7 +88,7 @@ protected:
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
[[nodiscard]] auto chown_impl(std::string api_path, uid_t uid, gid_t gid, [[nodiscard]] auto chown_impl(std::string api_path, uid_t uid, gid_t gid,
struct fuse_file_info *file_info) struct fuse_file_info *f_info)
-> api_error override; -> api_error override;
#else // FUSE_USE_VERSION < 30 #else // FUSE_USE_VERSION < 30
[[nodiscard]] auto chown_impl(std::string api_path, uid_t uid, gid_t gid) [[nodiscard]] auto chown_impl(std::string api_path, uid_t uid, gid_t gid)
@@ -96,43 +96,43 @@ protected:
#endif // FUSE_USE_VERSION >= 30 #endif // FUSE_USE_VERSION >= 30
[[nodiscard]] auto create_impl(std::string api_path, mode_t mode, [[nodiscard]] auto create_impl(std::string api_path, mode_t mode,
struct fuse_file_info *file_info) struct fuse_file_info *f_info)
-> api_error override; -> api_error override;
void destroy_impl(void *ptr) override; void destroy_impl(void *ptr) override;
[[nodiscard]] auto fallocate_impl(std::string api_path, int mode, [[nodiscard]] auto fallocate_impl(std::string api_path, int mode,
off_t offset, off_t length, off_t offset, off_t length,
struct fuse_file_info *file_info) struct fuse_file_info *f_info)
-> api_error override; -> api_error override;
[[nodiscard]] auto fgetattr_impl(std::string api_path, struct stat *unix_st, [[nodiscard]] auto fgetattr_impl(std::string api_path, struct stat *u_stat,
struct fuse_file_info *file_info) struct fuse_file_info *f_info)
-> api_error override; -> api_error override;
#if defined(__APPLE__) #if defined(__APPLE__)
[[nodiscard]] auto fsetattr_x_impl(std::string api_path, [[nodiscard]] auto fsetattr_x_impl(std::string api_path,
struct setattr_x *attr, struct setattr_x *attr,
struct fuse_file_info *file_info) struct fuse_file_info *f_info)
-> api_error override; -> api_error override;
#endif // defined(__APPLE__) #endif // defined(__APPLE__)
[[nodiscard]] auto fsync_impl(std::string api_path, int datasync, [[nodiscard]] auto fsync_impl(std::string api_path, int datasync,
struct fuse_file_info *file_info) struct fuse_file_info *f_info)
-> api_error override; -> api_error override;
#if FUSE_USE_VERSION < 30 #if FUSE_USE_VERSION < 30
[[nodiscard]] auto ftruncate_impl(std::string api_path, off_t size, [[nodiscard]] auto ftruncate_impl(std::string api_path, off_t size,
struct fuse_file_info *file_info) struct fuse_file_info *f_info)
-> api_error override; -> api_error override;
#endif // FUSE_USE_VERSION < 30 #endif // FUSE_USE_VERSION < 30
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
[[nodiscard]] auto getattr_impl(std::string api_path, struct stat *unix_st, [[nodiscard]] auto getattr_impl(std::string api_path, struct stat *u_stat,
struct fuse_file_info *file_info) struct fuse_file_info *f_info)
-> api_error override; -> api_error override;
#else // FUSE_USE_VERSION < 30 #else // FUSE_USE_VERSION < 30
[[nodiscard]] auto getattr_impl(std::string api_path, struct stat *unix_st) [[nodiscard]] auto getattr_impl(std::string api_path, struct stat *u_stat)
-> api_error override; -> api_error override;
#endif // FUSE_USE_VERSION >= 30 #endif // FUSE_USE_VERSION >= 30
@@ -150,43 +150,47 @@ protected:
auto init_impl(struct fuse_conn_info *conn) -> void * override; auto init_impl(struct fuse_conn_info *conn) -> void * override;
#endif // FUSE_USE_VERSION >= 30 #endif // FUSE_USE_VERSION >= 30
[[nodiscard]] auto ioctl_impl(std::string api_path, int cmd, void *arg,
struct fuse_file_info *f_info)
-> api_error override;
[[nodiscard]] auto mkdir_impl(std::string api_path, mode_t mode) [[nodiscard]] auto mkdir_impl(std::string api_path, mode_t mode)
-> api_error override; -> api_error override;
void notify_fuse_main_exit(int &ret) override; void notify_fuse_main_exit(int &ret) override;
[[nodiscard]] auto open_impl(std::string api_path, [[nodiscard]] auto open_impl(std::string api_path,
struct fuse_file_info *file_info) struct fuse_file_info *f_info)
-> api_error override; -> api_error override;
[[nodiscard]] auto opendir_impl(std::string api_path, [[nodiscard]] auto opendir_impl(std::string api_path,
struct fuse_file_info *file_info) struct fuse_file_info *f_info)
-> api_error override; -> api_error override;
[[nodiscard]] auto read_impl(std::string api_path, char *buffer, [[nodiscard]] auto read_impl(std::string api_path, char *buffer,
size_t read_size, off_t read_offset, size_t read_size, off_t read_offset,
struct fuse_file_info *file_info, struct fuse_file_info *f_info,
std::size_t &bytes_read) -> api_error override; std::size_t &bytes_read) -> api_error override;
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
[[nodiscard]] auto readdir_impl(std::string api_path, void *buf, [[nodiscard]] auto readdir_impl(std::string api_path, void *buf,
fuse_fill_dir_t fuse_fill_dir, off_t offset, fuse_fill_dir_t fuse_fill_dir, off_t offset,
struct fuse_file_info *file_info, struct fuse_file_info *f_info,
fuse_readdir_flags flags) fuse_readdir_flags flags)
-> api_error override; -> api_error override;
#else // FUSE_USE_VERSION < 30 #else // FUSE_USE_VERSION < 30
[[nodiscard]] auto readdir_impl(std::string api_path, void *buf, [[nodiscard]] auto readdir_impl(std::string api_path, void *buf,
fuse_fill_dir_t fuse_fill_dir, off_t offset, fuse_fill_dir_t fuse_fill_dir, off_t offset,
struct fuse_file_info *file_info) struct fuse_file_info *f_info)
-> api_error override; -> api_error override;
#endif // FUSE_USE_VERSION >= 30 #endif // FUSE_USE_VERSION >= 30
[[nodiscard]] auto release_impl(std::string api_path, [[nodiscard]] auto release_impl(std::string api_path,
struct fuse_file_info *file_info) struct fuse_file_info *f_info)
-> api_error override; -> api_error override;
[[nodiscard]] auto releasedir_impl(std::string api_path, [[nodiscard]] auto releasedir_impl(std::string api_path,
struct fuse_file_info *file_info) struct fuse_file_info *f_info)
-> api_error override; -> api_error override;
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
@@ -262,7 +266,7 @@ protected:
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
[[nodiscard]] auto truncate_impl(std::string api_path, off_t size, [[nodiscard]] auto truncate_impl(std::string api_path, off_t size,
struct fuse_file_info *file_info) struct fuse_file_info *f_info)
-> api_error override; -> api_error override;
#else // FUSE_USE_VERSION < 30 #else // FUSE_USE_VERSION < 30
[[nodiscard]] auto truncate_impl(std::string api_path, off_t size) [[nodiscard]] auto truncate_impl(std::string api_path, off_t size)
@@ -274,7 +278,7 @@ protected:
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
[[nodiscard]] auto utimens_impl(std::string api_path, [[nodiscard]] auto utimens_impl(std::string api_path,
const struct timespec tv[2], const struct timespec tv[2],
struct fuse_file_info *file_info) struct fuse_file_info *f_info)
-> api_error override; -> api_error override;
#else // FUSE_USE_VERSION < 30 #else // FUSE_USE_VERSION < 30
[[nodiscard]] auto utimens_impl(std::string api_path, [[nodiscard]] auto utimens_impl(std::string api_path,
@@ -284,29 +288,33 @@ protected:
[[nodiscard]] auto write_impl(std::string api_path, const char *buffer, [[nodiscard]] auto write_impl(std::string api_path, const char *buffer,
size_t write_size, off_t write_offset, size_t write_size, off_t write_offset,
struct fuse_file_info *file_info, struct fuse_file_info *f_info,
std::size_t &bytes_written) std::size_t &bytes_written)
-> api_error override; -> api_error override;
public: public:
[[nodiscard]] auto get_directory_item_count(const std::string &api_path) const [[nodiscard]] auto get_directory_item_count(std::string_view api_path) const
-> std::uint64_t override; -> std::uint64_t override;
[[nodiscard]] auto get_directory_items(const std::string &api_path) const [[nodiscard]] auto get_directory_items(std::string_view api_path) const
-> directory_item_list override; -> directory_item_list override;
[[nodiscard]] auto get_file_size(const std::string &api_path) const [[nodiscard]] auto get_file_size(std::string_view api_path) const
-> std::uint64_t override; -> std::uint64_t override;
[[nodiscard]] auto get_item_meta(const std::string &api_path, [[nodiscard]] auto get_item_meta(std::string_view api_path,
api_meta_map &meta) const api_meta_map &meta) const
-> api_error override; -> api_error override;
[[nodiscard]] auto get_item_meta(const std::string &api_path, [[nodiscard]] auto get_item_meta(std::string_view api_path,
const std::string &name, std::string_view name,
std::string &value) const std::string &value) const
-> api_error override; -> api_error override;
[[nodiscard]] auto get_item_stat(std::uint64_t handle,
struct stat64 *u_stat) const
-> api_error override;
[[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override; [[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override;
[[nodiscard]] auto get_total_item_count() const -> std::uint64_t override; [[nodiscard]] auto get_total_item_count() const -> std::uint64_t override;
@@ -316,21 +324,21 @@ public:
void get_volume_info(UINT64 &total_size, UINT64 &free_size, void get_volume_info(UINT64 &total_size, UINT64 &free_size,
std::string &volume_label) const override; std::string &volume_label) const override;
[[nodiscard]] auto is_processing(const std::string &api_path) const [[nodiscard]] auto is_processing(std::string_view api_path) const
-> bool override; -> bool override;
[[nodiscard]] auto rename_directory(const std::string &from_api_path, [[nodiscard]] auto rename_directory(std::string_view from_api_path,
const std::string &to_api_path) std::string_view to_api_path)
-> int override; -> int override;
[[nodiscard]] auto rename_file(const std::string &from_api_path, [[nodiscard]] auto rename_file(std::string_view from_api_path,
const std::string &to_api_path, bool overwrite) std::string_view to_api_path, bool overwrite)
-> int override; -> int override;
void set_item_meta(const std::string &api_path, const std::string &key, void set_item_meta(std::string_view api_path, std::string_view key,
const std::string &value) override; std::string_view value) override;
void set_item_meta(const std::string &api_path, void set_item_meta(std::string_view api_path,
const api_meta_map &meta) override; const api_meta_map &meta) override;
}; };
} // namespace repertory } // namespace repertory

View File

@@ -47,11 +47,11 @@ protected:
-> api_error override; -> api_error override;
protected: protected:
[[nodiscard]] auto check_access(const std::string &api_path, int mask) const [[nodiscard]] auto check_access(std::string_view api_path, int mask) const
-> api_error; -> api_error;
[[nodiscard]] auto [[nodiscard]] auto
check_and_perform(const std::string &api_path, int parent_mask, check_and_perform(std::string_view api_path, int parent_mask,
const std::function<api_error(api_meta_map &meta)> &action) const std::function<api_error(api_meta_map &meta)> &action)
-> api_error; -> api_error;
@@ -86,22 +86,21 @@ protected:
-> mode_t; -> mode_t;
static void get_timespec_from_meta(const api_meta_map &meta, static void get_timespec_from_meta(const api_meta_map &meta,
const std::string &name, std::string_view name,
struct timespec &ts); struct timespec &ts);
[[nodiscard]] static auto get_uid_from_meta(const api_meta_map &meta) [[nodiscard]] static auto get_uid_from_meta(const api_meta_map &meta)
-> uid_t; -> uid_t;
#if defined(__APPLE__) #if defined(__APPLE__)
[[nodiscard]] auto parse_xattr_parameters(const char *name, [[nodiscard]] auto
const uint32_t &position, parse_xattr_parameters(const char *name, const uint32_t &position,
std::string &attribute_name, std::string &attribute_name, std::string_view api_path)
const std::string &api_path)
-> api_error; -> api_error;
#else // !defined(__APPLE__) #else // !defined(__APPLE__)
[[nodiscard]] auto parse_xattr_parameters(const char *name, [[nodiscard]] auto parse_xattr_parameters(const char *name,
std::string &attribute_name, std::string &attribute_name,
const std::string &api_path) std::string_view api_path)
-> api_error; -> api_error;
#endif // defined(__APPLE__) #endif // defined(__APPLE__)
@@ -109,30 +108,31 @@ protected:
[[nodiscard]] auto [[nodiscard]] auto
parse_xattr_parameters(const char *name, const char *value, size_t size, parse_xattr_parameters(const char *name, const char *value, size_t size,
const uint32_t &position, std::string &attribute_name, const uint32_t &position, std::string &attribute_name,
const std::string &api_path) -> api_error; std::string_view api_path) -> api_error;
#else // !defined(__APPLE__) #else // !defined(__APPLE__)
[[nodiscard]] auto parse_xattr_parameters(const char *name, const char *value, [[nodiscard]] auto
size_t size, parse_xattr_parameters(const char *name, const char *value, size_t size,
std::string &attribute_name, std::string &attribute_name, std::string_view api_path)
const std::string &api_path)
-> api_error; -> api_error;
#endif // defined(__APPLE__) #endif // defined(__APPLE__)
static void populate_stat(const std::string &api_path, static void populate_stat(std::string_view api_path,
std::uint64_t size_or_count, std::uint64_t size_or_count,
const api_meta_map &meta, bool directory, const api_meta_map &meta, bool directory,
i_provider &provider, struct stat *st); i_provider &provider, struct stat *u_stat);
static void set_timespec_from_meta(const api_meta_map &meta, static void set_timespec_from_meta(const api_meta_map &meta,
const std::string &name, std::string_view name,
struct timespec &ts); struct timespec &ts);
public: public:
[[nodiscard]] auto check_owner(const std::string &api_path) const [[nodiscard]] auto check_owner(std::string_view api_path) const
-> api_error override; -> api_error override;
[[nodiscard]] auto check_parent_access(const std::string &api_path, [[nodiscard]] auto check_parent_access(std::string_view api_path,
int mask) const -> api_error override; int mask) const -> api_error override;
[[nodiscard]] static auto validate_timespec(const timespec &spec) -> bool;
}; };
} // namespace repertory } // namespace repertory

View File

@@ -26,37 +26,43 @@
#include "types/repertory.hpp" #include "types/repertory.hpp"
namespace repertory { namespace repertory {
inline constexpr const int repertory_ioctl_fd_command = 0x102010;
class i_fuse_drive { class i_fuse_drive {
INTERFACE_SETUP(i_fuse_drive); INTERFACE_SETUP(i_fuse_drive);
public: public:
[[nodiscard]] virtual auto check_owner(const std::string &api_path) const [[nodiscard]] virtual auto check_owner(std::string_view api_path) const
-> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto check_parent_access(const std::string &api_path, [[nodiscard]] virtual auto check_parent_access(std::string_view api_path,
int mask) const int mask) const
-> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
get_directory_item_count(const std::string &api_path) const get_directory_item_count(std::string_view api_path) const
-> std::uint64_t = 0; -> std::uint64_t = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
get_directory_items(const std::string &api_path) const get_directory_items(std::string_view api_path) const
-> directory_item_list = 0; -> directory_item_list = 0;
[[nodiscard]] virtual auto get_file_size(const std::string &api_path) const [[nodiscard]] virtual auto get_file_size(std::string_view api_path) const
-> std::uint64_t = 0; -> std::uint64_t = 0;
[[nodiscard]] virtual auto get_item_meta(const std::string &api_path, [[nodiscard]] virtual auto get_item_meta(std::string_view api_path,
api_meta_map &meta) const api_meta_map &meta) const
-> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto get_item_meta(const std::string &api_path, [[nodiscard]] virtual auto get_item_meta(std::string_view api_path,
const std::string &name, std::string_view name,
std::string &value) const std::string &value) const
-> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto get_item_stat(std::uint64_t handle,
struct stat64 *u_stat) const
-> api_error = 0;
[[nodiscard]] virtual auto get_total_drive_space() const -> std::uint64_t = 0; [[nodiscard]] virtual auto get_total_drive_space() const -> std::uint64_t = 0;
[[nodiscard]] virtual auto get_total_item_count() const -> std::uint64_t = 0; [[nodiscard]] virtual auto get_total_item_count() const -> std::uint64_t = 0;
@@ -66,22 +72,21 @@ public:
virtual void get_volume_info(UINT64 &total_size, UINT64 &free_size, virtual void get_volume_info(UINT64 &total_size, UINT64 &free_size,
std::string &volume_label) const = 0; std::string &volume_label) const = 0;
[[nodiscard]] virtual auto is_processing(const std::string &api_path) const [[nodiscard]] virtual auto is_processing(std::string_view api_path) const
-> bool = 0; -> bool = 0;
[[nodiscard]] virtual auto rename_directory(const std::string &from_api_path, [[nodiscard]] virtual auto rename_directory(std::string_view from_api_path,
const std::string &to_api_path) std::string_view to_api_path)
-> int = 0; -> int = 0;
[[nodiscard]] virtual auto rename_file(const std::string &from_api_path, [[nodiscard]] virtual auto rename_file(std::string_view from_api_path,
const std::string &to_api_path, std::string_view to_api_path,
bool overwrite) -> int = 0; bool overwrite) -> int = 0;
virtual void set_item_meta(const std::string &api_path, virtual void set_item_meta(std::string_view api_path, std::string_view key,
const std::string &key, std::string_view value) = 0;
const std::string &value) = 0;
virtual void set_item_meta(const std::string &api_path, virtual void set_item_meta(std::string_view api_path,
const api_meta_map &meta) = 0; const api_meta_map &meta) = 0;
}; };
} // namespace repertory } // namespace repertory

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