Refactor logging, add cache-size, fs-event-log (#163)
Much appreciated! Merged. :)
This commit is contained in:
parent
b9ea6ca4c9
commit
441a0d69ed
|
|
@ -0,0 +1,134 @@
|
||||||
|
# Log Management Guide
|
||||||
|
|
||||||
|
This guide covers log configuration and rotation for `pcloudcc`.
|
||||||
|
|
||||||
|
## Log Files
|
||||||
|
|
||||||
|
`pcloudcc` supports two types of logs:
|
||||||
|
|
||||||
|
1. **Debug Log** - Operational information, errors, and debug messages
|
||||||
|
- Default location: `~/.pcloud/debug.log`
|
||||||
|
- Configure with: `--log-path` and `--log-level`
|
||||||
|
|
||||||
|
2. **Filesystem Events Log** - Clean log of file/folder operations only
|
||||||
|
- Disabled by default
|
||||||
|
- Enable with: `--fs-event-log`
|
||||||
|
|
||||||
|
## Log Configuration
|
||||||
|
|
||||||
|
### Log Level
|
||||||
|
|
||||||
|
Control verbosity with `--log-level`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Errors only
|
||||||
|
pcloudcc -u user@example.com -d --log-level ERROR
|
||||||
|
|
||||||
|
# Normal operation (default)
|
||||||
|
pcloudcc -u user@example.com -d --log-level INFO
|
||||||
|
|
||||||
|
# Detailed debugging
|
||||||
|
pcloudcc -u user@example.com -d --log-level DEBUG
|
||||||
|
|
||||||
|
# Disable logging
|
||||||
|
pcloudcc -u user@example.com -d --log-level NONE
|
||||||
|
```
|
||||||
|
|
||||||
|
Available levels: `NONE`, `ERROR`, `WARNING`, `INFO`, `NOTICE`, `DEBUG`
|
||||||
|
|
||||||
|
### Custom Log Path
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# System-wide log
|
||||||
|
pcloudcc -u user@example.com -d --log-path /var/log/pcloudcc.log
|
||||||
|
|
||||||
|
# Custom user location
|
||||||
|
pcloudcc -u user@example.com -d --log-path ~/logs/pcloud.log
|
||||||
|
```
|
||||||
|
|
||||||
|
### Filesystem Events Log
|
||||||
|
|
||||||
|
Enable a separate log containing only filesystem events:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pcloudcc -u user@example.com -d --fs-event-log ~/.pcloud/fs-events.log
|
||||||
|
```
|
||||||
|
|
||||||
|
Event format: `<timestamp> <event_type> <path>`
|
||||||
|
|
||||||
|
Example events:
|
||||||
|
```
|
||||||
|
Wed, 12 Nov 2025 05:24:23.032 +0000 file deleted /tmp/xxx
|
||||||
|
Wed, 12 Nov 2025 05:24:47.861 +0000 folder moved /tmp/test2 -> /tmp/test3
|
||||||
|
Wed, 12 Nov 2025 05:25:10.445 +0000 file created /tmp/newfile.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
## Log Rotation
|
||||||
|
|
||||||
|
### System-Wide (with logrotate)
|
||||||
|
|
||||||
|
Install the provided configuration:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo cp pcloudcc.logrotate /etc/logrotate.d/pcloudcc
|
||||||
|
```
|
||||||
|
|
||||||
|
This rotates logs daily, keeps 7 days of history, and compresses old logs.
|
||||||
|
|
||||||
|
### User-Specific Rotation
|
||||||
|
|
||||||
|
Create `~/.logrotate.conf`:
|
||||||
|
|
||||||
|
```
|
||||||
|
/home/username/.pcloud/debug.log /home/username/.pcloud/fs-events.log {
|
||||||
|
weekly
|
||||||
|
rotate 4
|
||||||
|
compress
|
||||||
|
missingok
|
||||||
|
notifempty
|
||||||
|
create 0600 username username
|
||||||
|
maxsize 50M
|
||||||
|
postrotate
|
||||||
|
pkill -USR2 -u username pcloudcc 2>/dev/null || true
|
||||||
|
endscript
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Add to crontab:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
crontab -e
|
||||||
|
# Add this line:
|
||||||
|
0 2 * * * /usr/sbin/logrotate -s ~/.logrotate.state ~/.logrotate.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manual Rotation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Move current logs
|
||||||
|
mv ~/.pcloud/debug.log ~/.pcloud/debug.log.old
|
||||||
|
mv ~/.pcloud/fs-events.log ~/.pcloud/fs-events.log.old
|
||||||
|
|
||||||
|
# Signal pcloudcc to reopen logs
|
||||||
|
pkill -SIGUSR2 pcloudcc
|
||||||
|
```
|
||||||
|
|
||||||
|
## Cache Management
|
||||||
|
|
||||||
|
Configure cache size (default 5GB):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Set to 10GB
|
||||||
|
pcloudcc -u user@example.com -d --cache-size 10
|
||||||
|
|
||||||
|
# Set to 1GB for limited storage
|
||||||
|
pcloudcc -u user@example.com -d --cache-size 1
|
||||||
|
```
|
||||||
|
|
||||||
|
Check cache usage:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
du -sh ~/.pcloud/Cache
|
||||||
|
```
|
||||||
|
|
||||||
|
Cache is stored in `~/.pcloud/Cache/` and managed automatically by `pcloudcc`.
|
||||||
17
Makefile
17
Makefile
|
|
@ -25,6 +25,7 @@ CPPOBJ := $(notdir $(CPPSRC:%.cpp=%.o))
|
||||||
|
|
||||||
DESTDIR := /usr/local
|
DESTDIR := /usr/local
|
||||||
STATIC := 1
|
STATIC := 1
|
||||||
|
FULLSTATIC := 0
|
||||||
BUILD := release
|
BUILD := release
|
||||||
SSLDBGLVL := 0
|
SSLDBGLVL := 0
|
||||||
|
|
||||||
|
|
@ -45,6 +46,12 @@ else
|
||||||
$(error Invalid BUILD. Use 'debug' or 'release')
|
$(error Invalid BUILD. Use 'debug' or 'release')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(FULLSTATIC), 1)
|
||||||
|
# Force static linking of all libraries
|
||||||
|
LIBLDFLAGS += -static
|
||||||
|
EXECLDFLAGS += -static
|
||||||
|
endif
|
||||||
|
|
||||||
CFLAGS += $(DIST_CFLAGS)
|
CFLAGS += $(DIST_CFLAGS)
|
||||||
CXXFLAGS += $(DIST_CXXFLAGS)
|
CXXFLAGS += $(DIST_CXXFLAGS)
|
||||||
LIBLDFLAGS += $(LDFLAGS)
|
LIBLDFLAGS += $(LDFLAGS)
|
||||||
|
|
@ -63,7 +70,7 @@ else
|
||||||
EXECLDFLAGS += $(LIBLDFLAGS)
|
EXECLDFLAGS += $(LIBLDFLAGS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: all clean install uninstall
|
.PHONY: all clean install install-logrotate uninstall
|
||||||
|
|
||||||
all: $(TARGETS)
|
all: $(TARGETS)
|
||||||
|
|
||||||
|
|
@ -88,6 +95,14 @@ ifeq ($(STATIC), 0)
|
||||||
install -m 755 libpcloudcc_lib.so $(DESTDIR)/lib/libpcloudcc_lib.so
|
install -m 755 libpcloudcc_lib.so $(DESTDIR)/lib/libpcloudcc_lib.so
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
install-logrotate:
|
||||||
|
@echo "Installing logrotate configuration (requires root)..."
|
||||||
|
install -D -m 644 pcloudcc.logrotate /etc/logrotate.d/pcloudcc
|
||||||
|
@echo "Logrotate configuration installed to /etc/logrotate.d/pcloudcc"
|
||||||
|
@echo "Note: This handles system-wide logs at /var/log/pcloudcc.log"
|
||||||
|
@echo "For user-specific logs, see comments in pcloudcc.logrotate"
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
rm -f $(DESTDIR)/bin/pcloudcc
|
rm -f $(DESTDIR)/bin/pcloudcc
|
||||||
rm -f $(DESTDIR)/lib/libpcloudcc_lib.so
|
rm -f $(DESTDIR)/lib/libpcloudcc_lib.so
|
||||||
|
rm -f /etc/logrotate.d/pcloudcc
|
||||||
|
|
|
||||||
|
|
@ -39,3 +39,7 @@ file.
|
||||||
|
|
||||||
- [Usage Guide](./doc/USAGE.md): Read this if you're unsure how to start using
|
- [Usage Guide](./doc/USAGE.md): Read this if you're unsure how to start using
|
||||||
`pcloudcc`.
|
`pcloudcc`.
|
||||||
|
|
||||||
|
- [Log Management Guide](./LOG-MANAGEMENT.md): Read this to configure log rotation,
|
||||||
|
cache size limits, and custom log paths. To set up automatic log rotation, copy
|
||||||
|
`pcloudcc.logrotate` to `/etc/logrotate.d/pcloudcc`.
|
||||||
|
|
|
||||||
165
doc/USAGE.md
165
doc/USAGE.md
|
|
@ -4,7 +4,109 @@
|
||||||
|
|
||||||
Terminal command is pcloudcc and -h option prints short options description.
|
Terminal command is pcloudcc and -h option prints short options description.
|
||||||
|
|
||||||
> pcloudcc -h
|
```bash
|
||||||
|
pcloudcc -h
|
||||||
|
```
|
||||||
|
|
||||||
|
## New Options
|
||||||
|
|
||||||
|
### Cache Size Management
|
||||||
|
|
||||||
|
By default, the cache is limited to 5GB. You can adjust this with `--cache-size` (value in GB):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Set cache to 10GB
|
||||||
|
pcloudcc -u example@myemail.com -d --cache-size 10
|
||||||
|
|
||||||
|
# Set to 1GB for limited storage systems
|
||||||
|
pcloudcc -u example@myemail.com -d --cache-size 1
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Log Path
|
||||||
|
|
||||||
|
By default, logs are written to `~/.pcloud/debug.log`. You can specify a custom path:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# System-wide log (requires permissions)
|
||||||
|
pcloudcc -u example@myemail.com -d --log-path /var/log/pcloudcc.log
|
||||||
|
|
||||||
|
# Custom user log
|
||||||
|
pcloudcc -u example@myemail.com -d --log-path ~/my-pcloud.log
|
||||||
|
```
|
||||||
|
|
||||||
|
See [LOG-MANAGEMENT.md](../LOG-MANAGEMENT.md) for log rotation configuration.
|
||||||
|
|
||||||
|
### Log Level Control
|
||||||
|
|
||||||
|
By default, the logging level is set to INFO. You can adjust verbosity with `--log-level`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Minimal logging (errors only)
|
||||||
|
pcloudcc -u example@myemail.com -d --log-level ERROR
|
||||||
|
|
||||||
|
# Quiet mode (no logging)
|
||||||
|
pcloudcc -u example@myemail.com -d --log-level NONE
|
||||||
|
|
||||||
|
# Detailed logging for troubleshooting
|
||||||
|
pcloudcc -u example@myemail.com -d --log-level DEBUG
|
||||||
|
```
|
||||||
|
|
||||||
|
Available levels (from least to most verbose):
|
||||||
|
- `NONE` - Disable all logging
|
||||||
|
- `ERROR` - Only critical errors
|
||||||
|
- `WARNING` - Errors and warnings
|
||||||
|
- `INFO` - Normal operation info (default)
|
||||||
|
- `NOTICE` - Informational notices
|
||||||
|
- `DEBUG` - Detailed debug information
|
||||||
|
|
||||||
|
### Filesystem Events Log
|
||||||
|
|
||||||
|
Enable a separate log containing only filesystem events (no debug messages):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pcloudcc -u example@myemail.com -d --fs-event-log ~/.pcloud/fs-events.log
|
||||||
|
```
|
||||||
|
|
||||||
|
**Event format:** `<timestamp> <event_type> <path>`
|
||||||
|
|
||||||
|
**Event types:**
|
||||||
|
- `file created`, `file modified`, `file deleted`, `file downloaded`
|
||||||
|
- `file moved <oldpath> -> <newpath>`
|
||||||
|
- `folder created`, `folder deleted`
|
||||||
|
- `folder moved <oldpath> -> <newpath>`
|
||||||
|
|
||||||
|
**Example log entries:**
|
||||||
|
```
|
||||||
|
Wed, 12 Nov 2025 05:24:23.032 +0000 file deleted /tmp/xxx
|
||||||
|
Wed, 12 Nov 2025 05:24:47.861 +0000 folder moved /tmp/test2 -> /tmp/test3
|
||||||
|
Wed, 12 Nov 2025 05:25:10.445 +0000 file created /tmp/newfile.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
See [LOG-MANAGEMENT.md](../LOG-MANAGEMENT.md) for monitoring scripts and log rotation setup.
|
||||||
|
|
||||||
|
### FUSE Mount Options
|
||||||
|
|
||||||
|
Pass custom FUSE mount options with `--fuse-opts`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Allow other users to access the mount
|
||||||
|
pcloudcc -u example@myemail.com -d --fuse-opts allow_other
|
||||||
|
|
||||||
|
# Multiple options (comma-separated)
|
||||||
|
pcloudcc -u example@myemail.com -d --fuse-opts allow_other,allow_root
|
||||||
|
|
||||||
|
# Set custom permissions
|
||||||
|
pcloudcc -u example@myemail.com -d --fuse-opts default_permissions,uid=1000,gid=1000
|
||||||
|
```
|
||||||
|
|
||||||
|
**Common FUSE options:**
|
||||||
|
- `allow_other` - Allow all users to access files (requires `/etc/fuse.conf` setting)
|
||||||
|
- `allow_root` - Allow root to access files
|
||||||
|
- `default_permissions` - Enable kernel permission checking
|
||||||
|
- `uid=N`, `gid=N` - Set file owner/group
|
||||||
|
- `umask=OCTAL` - Set file permission mask
|
||||||
|
|
||||||
|
See `man fuse` for complete list of available options.
|
||||||
|
|
||||||
## First Use
|
## First Use
|
||||||
|
|
||||||
|
|
@ -28,11 +130,64 @@ Notice that a new user may take a while to mount. Please, be patient.
|
||||||
|
|
||||||
## Run as Daemon
|
## Run as Daemon
|
||||||
|
|
||||||
If you have saved your password, then you can run pcloudcc as a
|
**Daemon mode (`-d`) is the recommended way to run pcloudcc in production.** Running in foreground mode can cause FUSE filesystem errors and crashes if interrupted.
|
||||||
background daemon. Verify the filesystem is mounted when the daemon
|
|
||||||
starts.
|
|
||||||
|
|
||||||
> pcloudcc -u example@myemail.com -d
|
If you have saved your password, then you can run pcloudcc as a background daemon:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pcloudcc -u example@myemail.com -d
|
||||||
|
```
|
||||||
|
|
||||||
|
With custom mount point, cache size, and log path:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pcloudcc -u example@myemail.com -d -m /mnt/pcloud --cache-size 10 --log-path /var/log/pcloudcc.log
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify the filesystem is mounted when the daemon starts:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mount | grep pCloud
|
||||||
|
ps aux | grep pcloudcc
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stopping the Daemon
|
||||||
|
|
||||||
|
To stop the daemon gracefully, use one of these methods:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Graceful shutdown (recommended)
|
||||||
|
pkill -TERM pcloudcc
|
||||||
|
|
||||||
|
# Or use the command prompt
|
||||||
|
pcloudcc -k
|
||||||
|
# Then type: finalize
|
||||||
|
```
|
||||||
|
|
||||||
|
**Important**: Do NOT use `kill -9` or interrupt with Ctrl+C, as this can cause filesystem corruption.
|
||||||
|
|
||||||
|
### Available Signals
|
||||||
|
|
||||||
|
- **SIGTERM / SIGINT**: Gracefully shut down the daemon
|
||||||
|
- **SIGHUP**: Terminate the daemon (exits the process)
|
||||||
|
- **SIGUSR1**: Dump internal debugging information (debug builds only)
|
||||||
|
- **SIGUSR2**: Reopen log files for rotation
|
||||||
|
|
||||||
|
#### Log Rotation with SIGUSR2
|
||||||
|
|
||||||
|
The daemon responds to SIGUSR2 by reopening both the debug log and fs-events log (if enabled). This allows safe log rotation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Manual log rotation
|
||||||
|
mv ~/.pcloud/debug.log ~/.pcloud/debug.log.old
|
||||||
|
pkill -SIGUSR2 pcloudcc
|
||||||
|
|
||||||
|
# With fs-events log
|
||||||
|
mv ~/.pcloud/fs-events.log ~/.pcloud/fs-events.log.old
|
||||||
|
pkill -SIGUSR2 pcloudcc
|
||||||
|
```
|
||||||
|
|
||||||
|
For automatic log rotation with logrotate, see [LOG-MANAGEMENT.md](../LOG-MANAGEMENT.md).
|
||||||
|
|
||||||
## Command Prompt
|
## Command Prompt
|
||||||
|
|
||||||
|
|
|
||||||
79
main.cpp
79
main.cpp
|
|
@ -25,6 +25,7 @@
|
||||||
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
DAMAGE.
|
DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
@ -33,6 +34,7 @@
|
||||||
#include "control_tools.h"
|
#include "control_tools.h"
|
||||||
|
|
||||||
#include "pclsync_lib.h"
|
#include "pclsync_lib.h"
|
||||||
|
#include "pclsync/psettings.h"
|
||||||
|
|
||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
namespace ct = control_tools;
|
namespace ct = control_tools;
|
||||||
|
|
@ -71,7 +73,12 @@ int main(int argc, char **argv) {
|
||||||
("mountpoint,m", po::value<std::string>(), "Specify where pCloud filesystem is mounted.")
|
("mountpoint,m", po::value<std::string>(), "Specify where pCloud filesystem is mounted.")
|
||||||
("commands_only,k", po::bool_switch(&commands_only), "Open command prompt to interact with running daemon.")
|
("commands_only,k", po::bool_switch(&commands_only), "Open command prompt to interact with running daemon.")
|
||||||
("newuser,n", po::bool_switch(&newuser), "Register a new pCloud user account.")
|
("newuser,n", po::bool_switch(&newuser), "Register a new pCloud user account.")
|
||||||
("savepassword,s", po::bool_switch(&save_pass), "Save user password in the database.");
|
("savepassword,s", po::bool_switch(&save_pass), "Save user password in the database.")
|
||||||
|
("cache-size", po::value<uint64_t>(), "Maximum cache size in GB (default: 5GB).")
|
||||||
|
("log-path", po::value<std::string>(), "Custom path for debug.log (default: ~/.pcloud/debug.log).")
|
||||||
|
("log-level", po::value<std::string>(), "Logging level: NONE, ERROR, WARNING, INFO (default), NOTICE, DEBUG.")
|
||||||
|
("fs-event-log", po::value<std::string>(), "Path to filesystem events log (default: disabled).")
|
||||||
|
("fuse-opts,O", po::value<std::string>(), "FUSE mount options (e.g., 'allow_other,allow_root').");
|
||||||
|
|
||||||
po::command_line_parser parser{argc, argv};
|
po::command_line_parser parser{argc, argv};
|
||||||
po::positional_options_description p;
|
po::positional_options_description p;
|
||||||
|
|
@ -100,9 +107,16 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((!vm.count("username"))) {
|
// Environment variable fallbacks
|
||||||
|
if (!vm.count("username")) {
|
||||||
|
const char *env_user = std::getenv("PCLOUD_USER");
|
||||||
|
if (env_user && env_user[0])
|
||||||
|
username = env_user;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vm.count("username") && username.empty()) {
|
||||||
std::cout << "Username option is required, specify with "
|
std::cout << "Username option is required, specify with "
|
||||||
<< "-u or --username." << std::endl;
|
<< "-u or --username, or set PCLOUD_USER." << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,6 +132,11 @@ int main(int argc, char **argv) {
|
||||||
cc::clibrary::pclsync_lib::get_lib().set_username(username);
|
cc::clibrary::pclsync_lib::get_lib().set_username(username);
|
||||||
if (passwordsw) {
|
if (passwordsw) {
|
||||||
cc::clibrary::pclsync_lib::get_lib().read_password();
|
cc::clibrary::pclsync_lib::get_lib().read_password();
|
||||||
|
} else {
|
||||||
|
const char *env_pass = std::getenv("PCLOUD_ACCOUNT_PASSWORD");
|
||||||
|
if (env_pass && env_pass[0]) {
|
||||||
|
cc::clibrary::pclsync_lib::get_lib().set_password(std::string(env_pass));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cc::clibrary::pclsync_lib::get_lib().set_tfa_code(tfa_code);
|
cc::clibrary::pclsync_lib::get_lib().set_tfa_code(tfa_code);
|
||||||
cc::clibrary::pclsync_lib::get_lib().set_trusted_device(trusted_device);
|
cc::clibrary::pclsync_lib::get_lib().set_trusted_device(trusted_device);
|
||||||
|
|
@ -126,8 +145,13 @@ int main(int argc, char **argv) {
|
||||||
if (vm.count("passascrypto")) {
|
if (vm.count("passascrypto")) {
|
||||||
cc::clibrary::pclsync_lib::get_lib().set_crypto_pass(password);
|
cc::clibrary::pclsync_lib::get_lib().set_crypto_pass(password);
|
||||||
} else {
|
} else {
|
||||||
std::cout << "Enter crypto password." << std::endl;
|
const char *env_crypto = std::getenv("PCLOUD_CRYPTO_PASSWORD");
|
||||||
cc::clibrary::pclsync_lib::get_lib().read_cryptopass();
|
if (env_crypto && env_crypto[0]) {
|
||||||
|
cc::clibrary::pclsync_lib::get_lib().set_crypto_pass(std::string(env_crypto));
|
||||||
|
} else {
|
||||||
|
std::cout << "Enter crypto password." << std::endl;
|
||||||
|
cc::clibrary::pclsync_lib::get_lib().read_cryptopass();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
cc::clibrary::pclsync_lib::get_lib().setup_crypto_ = false;
|
cc::clibrary::pclsync_lib::get_lib().setup_crypto_ = false;
|
||||||
|
|
@ -137,6 +161,51 @@ int main(int argc, char **argv) {
|
||||||
vm["mountpoint"].as<std::string>());
|
vm["mountpoint"].as<std::string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vm.count("cache-size")) {
|
||||||
|
uint64_t cache_size_gb = vm["cache-size"].as<uint64_t>();
|
||||||
|
/* Validate cache size: minimum 1GB, maximum 1TB */
|
||||||
|
if (cache_size_gb < 1 || cache_size_gb > 1024) {
|
||||||
|
std::cerr << "error: cache-size must be between 1 and 1024 GB" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
uint64_t cache_size_bytes = cache_size_gb * 1024ULL * 1024ULL * 1024ULL;
|
||||||
|
char cache_size_str[32];
|
||||||
|
snprintf(cache_size_str, sizeof(cache_size_str), "%llu",
|
||||||
|
(unsigned long long)cache_size_bytes);
|
||||||
|
setenv("PCLOUD_CACHE_SIZE", cache_size_str, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm.count("log-path")) {
|
||||||
|
std::string log_path = vm["log-path"].as<std::string>();
|
||||||
|
/* Validate log path: must not be empty or start with /etc or /sys */
|
||||||
|
if (log_path.empty() || log_path.compare(0, 5, "/etc/") == 0 || log_path.compare(0, 5, "/sys/") == 0) {
|
||||||
|
std::cerr << "error: invalid log-path" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
setenv("PCLOUD_LOG_PATH", log_path.c_str(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm.count("log-level")) {
|
||||||
|
setenv("PCLOUD_LOG_LEVEL", vm["log-level"].as<std::string>().c_str(), 1);
|
||||||
|
} else {
|
||||||
|
/* Set default log level to INFO */
|
||||||
|
setenv("PCLOUD_LOG_LEVEL", "INFO", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm.count("fs-event-log")) {
|
||||||
|
std::string fs_event_log = vm["fs-event-log"].as<std::string>();
|
||||||
|
/* Validate fs-event-log path: must not be empty or start with /etc or /sys */
|
||||||
|
if (fs_event_log.empty() || fs_event_log.compare(0, 5, "/etc/") == 0 || fs_event_log.compare(0, 5, "/sys/") == 0) {
|
||||||
|
std::cerr << "error: invalid fs-event-log" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
setenv("PCLOUD_FS_EVENT_LOG", fs_event_log.c_str(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm.count("fuse-opts")) {
|
||||||
|
setenv("PCLOUD_FUSE_OPTS", vm["fuse-opts"].as<std::string>().c_str(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
cc::clibrary::pclsync_lib::get_lib().newuser_ = newuser;
|
cc::clibrary::pclsync_lib::get_lib().newuser_ = newuser;
|
||||||
cc::clibrary::pclsync_lib::get_lib().set_savepass(save_pass);
|
cc::clibrary::pclsync_lib::get_lib().set_savepass(save_pass);
|
||||||
cc::clibrary::pclsync_lib::get_lib().set_daemon(daemon);
|
cc::clibrary::pclsync_lib::get_lib().set_daemon(daemon);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
# Logrotate configuration for pcloudcc
|
||||||
|
# Install to: /etc/logrotate.d/pcloudcc
|
||||||
|
#
|
||||||
|
# For system-wide logs (when using --log-path /var/log/pcloudcc.log)
|
||||||
|
/var/log/pcloudcc.log /var/log/pcloudcc-fs-events.log {
|
||||||
|
daily
|
||||||
|
rotate 7
|
||||||
|
compress
|
||||||
|
delaycompress
|
||||||
|
missingok
|
||||||
|
notifempty
|
||||||
|
create 0644 root root
|
||||||
|
dateext
|
||||||
|
dateformat -%Y%m%d
|
||||||
|
maxsize 100M
|
||||||
|
|
||||||
|
postrotate
|
||||||
|
# Send USR2 signal to pcloudcc if it's running
|
||||||
|
# This causes the daemon to reopen both log files
|
||||||
|
# SIGUSR2 is used because SIGHUP exits the daemon and SIGUSR1 is for debug dumps
|
||||||
|
pkill -USR2 pcloudcc 2>/dev/null || true
|
||||||
|
endscript
|
||||||
|
}
|
||||||
|
|
||||||
|
# For user-specific logs in home directories
|
||||||
|
# Note: These need to be configured per-user since logrotate typically runs as root
|
||||||
|
# Users can add their own logrotate configs or use this template
|
||||||
|
#
|
||||||
|
# Example for user-specific log rotation (requires user cron job):
|
||||||
|
# Create ~/.logrotate.conf with:
|
||||||
|
#
|
||||||
|
# /home/username/.pcloud/debug.log /home/username/.pcloud/fs-events.log {
|
||||||
|
# weekly
|
||||||
|
# rotate 4
|
||||||
|
# compress
|
||||||
|
# missingok
|
||||||
|
# notifempty
|
||||||
|
# create 0600 username username
|
||||||
|
# maxsize 50M
|
||||||
|
#
|
||||||
|
# postrotate
|
||||||
|
# pkill -USR2 -u username pcloudcc 2>/dev/null || true
|
||||||
|
# endscript
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# Then add to user's crontab:
|
||||||
|
# 0 2 * * * /usr/sbin/logrotate -s ~/.logrotate.state ~/.logrotate.conf
|
||||||
211
pclsync/pdbg.c
211
pclsync/pdbg.c
|
|
@ -1,8 +1,10 @@
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "pdbg.h"
|
#include "pdbg.h"
|
||||||
|
|
@ -11,7 +13,65 @@
|
||||||
|
|
||||||
extern PSYNC_THREAD const char *psync_thread_name;
|
extern PSYNC_THREAD const char *psync_thread_name;
|
||||||
|
|
||||||
|
static FILE *log_file = NULL;
|
||||||
|
static FILE *fs_event_log = NULL;
|
||||||
|
static int fs_event_log_initialized = 0;
|
||||||
|
static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
static volatile sig_atomic_t log_reopen_requested = 0;
|
||||||
|
|
||||||
|
/* Runtime debug level - defaults to D_INFO */
|
||||||
|
unsigned int pdbg_runtime_level = D_INFO;
|
||||||
|
static int pdbg_level_initialized = 0;
|
||||||
|
|
||||||
|
/* Forward declaration */
|
||||||
|
static void do_reopen_log(void);
|
||||||
|
|
||||||
|
/* Initialize debug level from environment variable */
|
||||||
|
static void pdbg_init_level(void) {
|
||||||
|
if (pdbg_level_initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pdbg_level_initialized = 1;
|
||||||
|
|
||||||
|
const char *level_str = getenv("PCLOUD_LOG_LEVEL");
|
||||||
|
if (!level_str || level_str[0] == '\0') {
|
||||||
|
pdbg_runtime_level = D_INFO; /* default to INFO */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse log level string (case-insensitive) */
|
||||||
|
if (strcasecmp(level_str, "NONE") == 0) {
|
||||||
|
pdbg_runtime_level = D_NONE;
|
||||||
|
} else if (strcasecmp(level_str, "BUG") == 0 || strcasecmp(level_str, "DEBUG") == 0) {
|
||||||
|
pdbg_runtime_level = D_BUG;
|
||||||
|
} else if (strcasecmp(level_str, "CRITICAL") == 0) {
|
||||||
|
pdbg_runtime_level = D_CRITICAL;
|
||||||
|
} else if (strcasecmp(level_str, "ERROR") == 0) {
|
||||||
|
pdbg_runtime_level = D_ERROR;
|
||||||
|
} else if (strcasecmp(level_str, "WARNING") == 0 || strcasecmp(level_str, "WARN") == 0) {
|
||||||
|
pdbg_runtime_level = D_WARNING;
|
||||||
|
} else if (strcasecmp(level_str, "INFO") == 0) {
|
||||||
|
pdbg_runtime_level = D_INFO;
|
||||||
|
} else if (strcasecmp(level_str, "NOTICE") == 0) {
|
||||||
|
pdbg_runtime_level = D_NOTICE;
|
||||||
|
} else {
|
||||||
|
/* Invalid level, default to INFO */
|
||||||
|
pdbg_runtime_level = D_INFO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char *psync_debug_path() {
|
char *psync_debug_path() {
|
||||||
|
const char *custom_path = getenv("PCLOUD_LOG_PATH");
|
||||||
|
if (custom_path && custom_path[0] != '\0') {
|
||||||
|
size_t len = strlen(custom_path) + 1;
|
||||||
|
char *path = (char *)malloc(len);
|
||||||
|
if (!path) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
snprintf(path, len, "%s", custom_path);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
char *home = ppath_home();
|
char *home = ppath_home();
|
||||||
if (!home) {
|
if (!home) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -28,7 +88,24 @@ char *psync_debug_path() {
|
||||||
return sockpath;
|
return sockpath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *psync_fs_event_log_path() {
|
||||||
|
const char *custom_path = getenv("PCLOUD_FS_EVENT_LOG");
|
||||||
|
if (custom_path && custom_path[0] != '\0') {
|
||||||
|
size_t len = strlen(custom_path) + 1;
|
||||||
|
char *path = (char *)malloc(len);
|
||||||
|
if (!path) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
snprintf(path, len, "%s", custom_path);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int pdbg_printf(const char *file, const char *function, int unsigned line, int unsigned level, const char *fmt, ...) {
|
int pdbg_printf(const char *file, const char *function, int unsigned line, int unsigned level, const char *fmt, ...) {
|
||||||
|
/* Initialize debug level from environment on first call */
|
||||||
|
pdbg_init_level();
|
||||||
|
|
||||||
if (!IS_DEBUG)
|
if (!IS_DEBUG)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
|
@ -36,7 +113,6 @@ int pdbg_printf(const char *file, const char *function, int unsigned line, int u
|
||||||
unsigned long level;
|
unsigned long level;
|
||||||
const char *name;
|
const char *name;
|
||||||
} debug_levels[] = DEBUG_LEVELS;
|
} debug_levels[] = DEBUG_LEVELS;
|
||||||
static FILE *log = NULL;
|
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
char dttime[36], format[512];
|
char dttime[36], format[512];
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
@ -50,13 +126,39 @@ int pdbg_printf(const char *file, const char *function, int unsigned line, int u
|
||||||
errname = debug_levels[i].name;
|
errname = debug_levels[i].name;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (unlikely(!log)) {
|
|
||||||
char *path = psync_debug_path();
|
pthread_mutex_lock(&log_mutex);
|
||||||
log = fopen(path, "a+");
|
|
||||||
free(path);
|
/* Check if log rotation was requested via signal */
|
||||||
if (!log)
|
if (unlikely(log_reopen_requested)) {
|
||||||
return 1;
|
log_reopen_requested = 0;
|
||||||
|
do_reopen_log();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unlikely(!log_file)) {
|
||||||
|
char *path = psync_debug_path();
|
||||||
|
log_file = fopen(path, "a+");
|
||||||
|
free(path);
|
||||||
|
if (!log_file) {
|
||||||
|
pthread_mutex_unlock(&log_mutex);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create empty fs event log file on first call if configured */
|
||||||
|
if (unlikely(!fs_event_log_initialized)) {
|
||||||
|
fs_event_log_initialized = 1;
|
||||||
|
char *path = psync_fs_event_log_path();
|
||||||
|
if (path) {
|
||||||
|
/* Create empty file if it doesn't exist, or open existing */
|
||||||
|
FILE *f = fopen(path, "a+");
|
||||||
|
if (f) {
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
clock_gettime(CLOCK_REALTIME, &ts);
|
clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
time_format(ts.tv_sec, ts.tv_nsec, dttime);
|
time_format(ts.tv_sec, ts.tv_nsec, dttime);
|
||||||
threadid = pthread_self();
|
threadid = pthread_self();
|
||||||
|
|
@ -65,8 +167,99 @@ int pdbg_printf(const char *file, const char *function, int unsigned line, int u
|
||||||
dttime, u, psync_thread_name, errname, file, line, function, fmt);
|
dttime, u, psync_thread_name, errname, file, line, function, fmt);
|
||||||
format[sizeof(format) - 1] = 0;
|
format[sizeof(format) - 1] = 0;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vfprintf(log, format, ap);
|
vfprintf(log_file, format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
fflush(log);
|
fflush(log_file);
|
||||||
|
pthread_mutex_unlock(&log_mutex);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Called from signal handler - must be signal-safe (no malloc/file ops) */
|
||||||
|
void pdbg_reopen_log() {
|
||||||
|
log_reopen_requested = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Internal function to actually reopen the log - called from safe context */
|
||||||
|
static void do_reopen_log() {
|
||||||
|
char *path;
|
||||||
|
FILE *new_log;
|
||||||
|
|
||||||
|
/* Close existing log file if open */
|
||||||
|
if (log_file) {
|
||||||
|
fclose(log_file);
|
||||||
|
log_file = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open new log file */
|
||||||
|
path = psync_debug_path();
|
||||||
|
if (path) {
|
||||||
|
new_log = fopen(path, "a+");
|
||||||
|
free(path);
|
||||||
|
if (new_log) {
|
||||||
|
log_file = new_log;
|
||||||
|
/* Log a message about the rotation */
|
||||||
|
fprintf(log_file, "Log file reopened for rotation\n");
|
||||||
|
fflush(log_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Also reopen fs event log if it was open */
|
||||||
|
if (fs_event_log) {
|
||||||
|
fclose(fs_event_log);
|
||||||
|
fs_event_log = NULL;
|
||||||
|
|
||||||
|
path = psync_fs_event_log_path();
|
||||||
|
if (path) {
|
||||||
|
new_log = fopen(path, "a+");
|
||||||
|
free(path);
|
||||||
|
if (new_log) {
|
||||||
|
fs_event_log = new_log;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write a filesystem event to the fs-event log with timestamp */
|
||||||
|
void pdbg_write_fs_event(const char *fmt, ...) {
|
||||||
|
struct timespec ts;
|
||||||
|
char dttime[36];
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&log_mutex);
|
||||||
|
|
||||||
|
/* Check if log rotation was requested */
|
||||||
|
if (unlikely(log_reopen_requested)) {
|
||||||
|
log_reopen_requested = 0;
|
||||||
|
do_reopen_log();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open fs event log if not already open */
|
||||||
|
if (unlikely(!fs_event_log)) {
|
||||||
|
char *path = psync_fs_event_log_path();
|
||||||
|
if (!path) {
|
||||||
|
/* FS event log not configured, skip */
|
||||||
|
pthread_mutex_unlock(&log_mutex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fs_event_log = fopen(path, "a+");
|
||||||
|
free(path);
|
||||||
|
if (!fs_event_log) {
|
||||||
|
pthread_mutex_unlock(&log_mutex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get timestamp */
|
||||||
|
clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
|
time_format(ts.tv_sec, ts.tv_nsec, dttime);
|
||||||
|
|
||||||
|
/* Write timestamp followed by event message */
|
||||||
|
fprintf(fs_event_log, "%s ", dttime);
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vfprintf(fs_event_log, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
fprintf(fs_event_log, "\n");
|
||||||
|
fflush(fs_event_log);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&log_mutex);
|
||||||
|
}
|
||||||
|
|
@ -11,18 +11,23 @@ extern "C" {
|
||||||
|
|
||||||
|
|
||||||
#define D_NONE 0
|
#define D_NONE 0
|
||||||
#define D_BUG 10
|
#define D_CRITICAL 10
|
||||||
#define D_CRITICAL 20
|
#define D_ERROR 20
|
||||||
#define D_ERROR 30
|
#define D_WARNING 30
|
||||||
#define D_WARNING 40
|
#define D_INFO 40
|
||||||
#define D_NOTICE 50
|
#define D_NOTICE 50
|
||||||
|
#define D_BUG 60
|
||||||
|
|
||||||
#define DEBUG_LEVELS {{D_BUG, "BUG"}, {D_CRITICAL, "CRITICAL ERROR"}, {D_ERROR, "ERROR"}, {D_WARNING, "WARNING"}, {D_NOTICE, "NOTICE" } }
|
#define DEBUG_LEVELS {{D_BUG, "DEBUG"}, {D_CRITICAL, "CRITICAL ERROR"}, {D_ERROR, "ERROR"}, {D_WARNING, "WARNING"}, {D_INFO, "INFO"}, {D_NOTICE, "NOTICE" } }
|
||||||
|
|
||||||
|
/* Compile-time debug level for conditional compilation */
|
||||||
#ifndef DEBUG_LEVEL
|
#ifndef DEBUG_LEVEL
|
||||||
#define DEBUG_LEVEL D_NOTICE
|
#define DEBUG_LEVEL D_NOTICE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Runtime debug level - can be set via environment variable */
|
||||||
|
extern unsigned int pdbg_runtime_level;
|
||||||
|
|
||||||
#define IS_DEBUG (DEBUG_LEVEL >= D_WARNING)
|
#define IS_DEBUG (DEBUG_LEVEL >= D_WARNING)
|
||||||
|
|
||||||
#if defined(assert)
|
#if defined(assert)
|
||||||
|
|
@ -31,7 +36,7 @@ extern "C" {
|
||||||
|
|
||||||
#define pdbg_logf(level, ...) \
|
#define pdbg_logf(level, ...) \
|
||||||
do { \
|
do { \
|
||||||
if (level <= DEBUG_LEVEL) \
|
if (level <= pdbg_runtime_level) \
|
||||||
pdbg_printf(__FILE__, __FUNCTION__, __LINE__, level, __VA_ARGS__); \
|
pdbg_printf(__FILE__, __FUNCTION__, __LINE__, level, __VA_ARGS__); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define pdbg_assert(cond) \
|
#define pdbg_assert(cond) \
|
||||||
|
|
@ -92,6 +97,8 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int pdbg_printf(const char *file, const char *function, int unsigned line, int unsigned level, const char *fmt, ...) PSYNC_COLD PSYNC_FORMAT(printf, 5, 6) PSYNC_NONNULL(5);
|
int pdbg_printf(const char *file, const char *function, int unsigned line, int unsigned level, const char *fmt, ...) PSYNC_COLD PSYNC_FORMAT(printf, 5, 6) PSYNC_NONNULL(5);
|
||||||
|
void pdbg_reopen_log(void);
|
||||||
|
void pdbg_write_fs_event(const char *fmt, ...) PSYNC_FORMAT(printf, 1, 2) PSYNC_NONNULL(1);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
||||||
138
pclsync/pdiff.c
138
pclsync/pdiff.c
|
|
@ -920,6 +920,21 @@ static void process_createfolder(const binresult *entry) {
|
||||||
psql_bind_uint(st2, 1, mtime);
|
psql_bind_uint(st2, 1, mtime);
|
||||||
psql_bind_uint(st2, 2, parentfolderid);
|
psql_bind_uint(st2, 2, parentfolderid);
|
||||||
psql_run(st2);
|
psql_run(st2);
|
||||||
|
|
||||||
|
// Log remote folder creation (both synced and FUSE-only)
|
||||||
|
{
|
||||||
|
char *folderpath = psync_fs_get_path_by_folderid(folderid);
|
||||||
|
if (likely(folderpath)) {
|
||||||
|
pdbg_write_fs_event("folder created %s", folderpath);
|
||||||
|
free(folderpath);
|
||||||
|
}
|
||||||
|
folderpath = pfolder_path(folderid, NULL);
|
||||||
|
if (likely(folderpath)) {
|
||||||
|
pdbg_logf(D_NOTICE, "remote folder created %s", folderpath);
|
||||||
|
free(folderpath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (psyncer_dl_has_folder(parentfolderid) &&
|
if (psyncer_dl_has_folder(parentfolderid) &&
|
||||||
!psync_is_name_to_ignore(name->str)) {
|
!psync_is_name_to_ignore(name->str)) {
|
||||||
psyncer_dl_queue_add(folderid);
|
psyncer_dl_queue_add(folderid);
|
||||||
|
|
@ -1075,6 +1090,10 @@ static void process_modifyfolder(const binresult *entry) {
|
||||||
psync_delete_backup_device(folderid);
|
psync_delete_backup_device(folderid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get old folder path before database update (for move detection)
|
||||||
|
char *oldfolderpath = psync_fs_get_path_by_folderid(folderid);
|
||||||
|
char *oldfolderpath_rel = pfolder_path(folderid, NULL);
|
||||||
|
|
||||||
mtime = papi_find_result2(meta, "modified", PARAM_NUM)->num;
|
mtime = papi_find_result2(meta, "modified", PARAM_NUM)->num;
|
||||||
psql_bind_uint(st, 1, parentfolderid);
|
psql_bind_uint(st, 1, parentfolderid);
|
||||||
psql_bind_uint(st, 2, userid);
|
psql_bind_uint(st, 2, userid);
|
||||||
|
|
@ -1087,6 +1106,27 @@ static void process_modifyfolder(const binresult *entry) {
|
||||||
psql_bind_uint(st, 8, folderid);
|
psql_bind_uint(st, 8, folderid);
|
||||||
psql_run(st);
|
psql_run(st);
|
||||||
|
|
||||||
|
// Log folder move/rename if location or name changed
|
||||||
|
{
|
||||||
|
int is_move = (oldparentfolderid != parentfolderid ||
|
||||||
|
strcmp(name->str, oldname) != 0);
|
||||||
|
if (is_move) {
|
||||||
|
char *newfolderpath = psync_fs_get_path_by_folderid(folderid);
|
||||||
|
if (likely(oldfolderpath && newfolderpath)) {
|
||||||
|
pdbg_write_fs_event("folder moved %s -> %s", oldfolderpath, newfolderpath);
|
||||||
|
}
|
||||||
|
free(newfolderpath);
|
||||||
|
|
||||||
|
char *newfolderpath_rel = pfolder_path(folderid, NULL);
|
||||||
|
if (likely(oldfolderpath_rel && newfolderpath_rel)) {
|
||||||
|
pdbg_logf(D_NOTICE, "remote folder moved %s -> %s", oldfolderpath_rel, newfolderpath_rel);
|
||||||
|
}
|
||||||
|
free(newfolderpath_rel);
|
||||||
|
}
|
||||||
|
free(oldfolderpath);
|
||||||
|
free(oldfolderpath_rel);
|
||||||
|
}
|
||||||
|
|
||||||
if (oldparentfolderid != parentfolderid) {
|
if (oldparentfolderid != parentfolderid) {
|
||||||
res = psql_prepare(
|
res = psql_prepare(
|
||||||
"UPDATE folder SET subdircnt=subdircnt-1, mtime=? WHERE id=?");
|
"UPDATE folder SET subdircnt=subdircnt-1, mtime=? WHERE id=?");
|
||||||
|
|
@ -1235,6 +1275,11 @@ static void process_deletefolder(const binresult *entry) {
|
||||||
meta = papi_find_result2(entry, "metadata", PARAM_HASH);
|
meta = papi_find_result2(entry, "metadata", PARAM_HASH);
|
||||||
folderid = papi_find_result2(meta, "folderid", PARAM_NUM)->num;
|
folderid = papi_find_result2(meta, "folderid", PARAM_NUM)->num;
|
||||||
ppathstatus_fldr_deleted(folderid);
|
ppathstatus_fldr_deleted(folderid);
|
||||||
|
|
||||||
|
// Get folder path BEFORE deletion from database
|
||||||
|
path = pfolder_path(folderid, NULL);
|
||||||
|
char *fullpath = psync_fs_get_path_by_folderid(folderid);
|
||||||
|
|
||||||
if (psyncer_dl_has_folder(folderid)) {
|
if (psyncer_dl_has_folder(folderid)) {
|
||||||
psyncer_dl_queue_del(folderid);
|
psyncer_dl_queue_del(folderid);
|
||||||
res = psql_query(
|
res = psql_query(
|
||||||
|
|
@ -1247,9 +1292,9 @@ static void process_deletefolder(const binresult *entry) {
|
||||||
psql_bind_uint(stmt, 2, folderid);
|
psql_bind_uint(stmt, 2, folderid);
|
||||||
psql_run_free(stmt);
|
psql_run_free(stmt);
|
||||||
if (psql_affected() == 1) {
|
if (psql_affected() == 1) {
|
||||||
path = pfolder_path(folderid, NULL);
|
char *syncpath = pfolder_path(folderid, NULL);
|
||||||
ptask_ldir_rm(row[0], folderid, row[1], path);
|
ptask_ldir_rm(row[0], folderid, row[1], syncpath);
|
||||||
free(path);
|
free(syncpath);
|
||||||
needdownload = 1;
|
needdownload = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1258,6 +1303,13 @@ static void process_deletefolder(const binresult *entry) {
|
||||||
psql_bind_uint(st, 1, folderid);
|
psql_bind_uint(st, 1, folderid);
|
||||||
psql_run(st);
|
psql_run(st);
|
||||||
if (psql_affected()) {
|
if (psql_affected()) {
|
||||||
|
// Log remote folder deletion (both synced and FUSE-only)
|
||||||
|
if (likely(fullpath)) {
|
||||||
|
pdbg_write_fs_event("folder deleted %s", fullpath);
|
||||||
|
}
|
||||||
|
if (likely(path)) {
|
||||||
|
pdbg_logf(D_NOTICE, "remote folder deleted %s", path);
|
||||||
|
}
|
||||||
psql_bind_uint(st2, 1,
|
psql_bind_uint(st2, 1,
|
||||||
papi_find_result2(meta, "modified", PARAM_NUM)->num);
|
papi_find_result2(meta, "modified", PARAM_NUM)->num);
|
||||||
psql_bind_uint(
|
psql_bind_uint(
|
||||||
|
|
@ -1265,6 +1317,10 @@ static void process_deletefolder(const binresult *entry) {
|
||||||
psql_run(st2);
|
psql_run(st2);
|
||||||
psync_fs_folder_deleted(folderid);
|
psync_fs_folder_deleted(folderid);
|
||||||
}
|
}
|
||||||
|
if (path)
|
||||||
|
free(path);
|
||||||
|
if (fullpath)
|
||||||
|
free(fullpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_for_deletedfileid(const binresult *meta) {
|
static void check_for_deletedfileid(const binresult *meta) {
|
||||||
|
|
@ -1392,6 +1448,21 @@ static void process_createfile(const binresult *entry) {
|
||||||
}
|
}
|
||||||
insert_revision(fileid, hash,
|
insert_revision(fileid, hash,
|
||||||
papi_find_result2(meta, "modified", PARAM_NUM)->num, size);
|
papi_find_result2(meta, "modified", PARAM_NUM)->num, size);
|
||||||
|
|
||||||
|
// Log all remote file creations (both synced and FUSE-only)
|
||||||
|
{
|
||||||
|
char *filepath = psync_fs_get_path_by_fileid(fileid);
|
||||||
|
if (likely(filepath)) {
|
||||||
|
pdbg_write_fs_event("file created %s", filepath);
|
||||||
|
free(filepath);
|
||||||
|
}
|
||||||
|
filepath = pfolder_file_path(fileid, NULL);
|
||||||
|
if (likely(filepath)) {
|
||||||
|
pdbg_logf(D_NOTICE, "remote file created %s", filepath);
|
||||||
|
free(filepath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (psyncer_dl_has_folder(parentfolderid) &&
|
if (psyncer_dl_has_folder(parentfolderid) &&
|
||||||
!psync_is_name_to_ignore(name->str)) {
|
!psync_is_name_to_ignore(name->str)) {
|
||||||
res = psql_query("SELECT syncid, localfolderid FROM syncedfolder "
|
res = psql_query("SELECT syncid, localfolderid FROM syncedfolder "
|
||||||
|
|
@ -1467,6 +1538,13 @@ static void process_modifyfile(const binresult *entry) {
|
||||||
oldsize = psync_get_number(row[2]);
|
oldsize = psync_get_number(row[2]);
|
||||||
if (psync_get_number(row[1]) == psync_my_userid)
|
if (psync_get_number(row[1]) == psync_my_userid)
|
||||||
used_quota -= oldsize;
|
used_quota -= oldsize;
|
||||||
|
|
||||||
|
// Get old path before database update (for move detection)
|
||||||
|
oldparentfolderid = psync_get_number(row[0]);
|
||||||
|
oldname = psync_get_lstring(row[4], &oldnamelen);
|
||||||
|
char *oldfilepath = psync_fs_get_path_by_fileid(fileid);
|
||||||
|
char *oldfilepath_rel = pfolder_file_path(fileid, NULL);
|
||||||
|
|
||||||
if (!st)
|
if (!st)
|
||||||
st = psql_prepare(
|
st = psql_prepare(
|
||||||
"UPDATE file SET id=?, parentfolderid=?, userid=?, size=?, hash=?, "
|
"UPDATE file SET id=?, parentfolderid=?, userid=?, size=?, hash=?, "
|
||||||
|
|
@ -1502,7 +1580,41 @@ static void process_modifyfile(const binresult *entry) {
|
||||||
psql_run(st);
|
psql_run(st);
|
||||||
insert_revision(fileid, hash,
|
insert_revision(fileid, hash,
|
||||||
papi_find_result2(meta, "modified", PARAM_NUM)->num, size);
|
papi_find_result2(meta, "modified", PARAM_NUM)->num, size);
|
||||||
oldparentfolderid = psync_get_number(row[0]);
|
|
||||||
|
// Log file move/rename or modification (both synced and FUSE-only)
|
||||||
|
{
|
||||||
|
int is_move = (oldparentfolderid != parentfolderid ||
|
||||||
|
name->length != oldnamelen ||
|
||||||
|
memcmp(name->str, oldname, oldnamelen) != 0);
|
||||||
|
int is_content_change = (hash != psync_get_number(row[3]) || size != oldsize);
|
||||||
|
|
||||||
|
if (is_move) {
|
||||||
|
char *newfilepath = psync_fs_get_path_by_fileid(fileid);
|
||||||
|
if (likely(oldfilepath && newfilepath)) {
|
||||||
|
pdbg_write_fs_event("file moved %s -> %s", oldfilepath, newfilepath);
|
||||||
|
}
|
||||||
|
free(newfilepath);
|
||||||
|
|
||||||
|
char *newfilepath_rel = pfolder_file_path(fileid, NULL);
|
||||||
|
if (likely(oldfilepath_rel && newfilepath_rel)) {
|
||||||
|
pdbg_logf(D_NOTICE, "remote file moved %s -> %s", oldfilepath_rel, newfilepath_rel);
|
||||||
|
}
|
||||||
|
free(newfilepath_rel);
|
||||||
|
} else if (is_content_change) {
|
||||||
|
char *filepath = psync_fs_get_path_by_fileid(fileid);
|
||||||
|
if (likely(filepath)) {
|
||||||
|
pdbg_write_fs_event("file modified %s", filepath);
|
||||||
|
free(filepath);
|
||||||
|
}
|
||||||
|
filepath = pfolder_file_path(fileid, NULL);
|
||||||
|
if (likely(filepath)) {
|
||||||
|
pdbg_logf(D_NOTICE, "remote file modified %s", filepath);
|
||||||
|
free(filepath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(oldfilepath);
|
||||||
|
free(oldfilepath_rel);
|
||||||
|
}
|
||||||
oldsync = psyncer_dl_has_folder(oldparentfolderid);
|
oldsync = psyncer_dl_has_folder(oldparentfolderid);
|
||||||
if (oldparentfolderid == parentfolderid)
|
if (oldparentfolderid == parentfolderid)
|
||||||
newsync = oldsync;
|
newsync = oldsync;
|
||||||
|
|
@ -1517,11 +1629,12 @@ static void process_modifyfile(const binresult *entry) {
|
||||||
path = pfolder_file_path(fileid, NULL);
|
path = pfolder_file_path(fileid, NULL);
|
||||||
ptask_lfile_rm(fileid, path);
|
ptask_lfile_rm(fileid, path);
|
||||||
free(path);
|
free(path);
|
||||||
|
free(oldfilepath);
|
||||||
|
free(oldfilepath_rel);
|
||||||
needdownload = 1;
|
needdownload = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lneeddownload = hash != psync_get_number(row[3]) || size != oldsize;
|
lneeddownload = hash != psync_get_number(row[3]) || size != oldsize;
|
||||||
oldname = psync_get_lstring(row[4], &oldnamelen);
|
|
||||||
if (lneeddownload)
|
if (lneeddownload)
|
||||||
pdownload_tasks_delete(fileid, 0, 0);
|
pdownload_tasks_delete(fileid, 0, 0);
|
||||||
needrename = oldparentfolderid != parentfolderid ||
|
needrename = oldparentfolderid != parentfolderid ||
|
||||||
|
|
@ -1622,13 +1735,28 @@ static void process_deletefile(const binresult *entry) {
|
||||||
needdownload = 1;
|
needdownload = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Get path BEFORE deleting from database
|
||||||
|
path = pfolder_file_path(fileid, NULL);
|
||||||
|
char *fullpath = psync_fs_get_path_by_fileid(fileid);
|
||||||
|
|
||||||
psql_bind_uint(st, 1, fileid);
|
psql_bind_uint(st, 1, fileid);
|
||||||
psql_run(st);
|
psql_run(st);
|
||||||
if (psql_affected()) {
|
if (psql_affected()) {
|
||||||
|
// Log all remote file deletions (both synced and FUSE-only)
|
||||||
|
if (likely(fullpath)) {
|
||||||
|
pdbg_write_fs_event("file deleted %s", fullpath);
|
||||||
|
}
|
||||||
|
if (likely(path)) {
|
||||||
|
pdbg_logf(D_NOTICE, "remote file deleted %s", path);
|
||||||
|
}
|
||||||
if (papi_find_result2(meta, "ismine", PARAM_BOOL)->num)
|
if (papi_find_result2(meta, "ismine", PARAM_BOOL)->num)
|
||||||
used_quota -= papi_find_result2(meta, "size", PARAM_NUM)->num;
|
used_quota -= papi_find_result2(meta, "size", PARAM_NUM)->num;
|
||||||
psync_fs_file_deleted(fileid);
|
psync_fs_file_deleted(fileid);
|
||||||
}
|
}
|
||||||
|
if (path)
|
||||||
|
free(path);
|
||||||
|
if (fullpath)
|
||||||
|
free(fullpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void start_download() {
|
static void start_download() {
|
||||||
|
|
|
||||||
|
|
@ -861,6 +861,7 @@ static int task_download_file(download_task_t *dt) {
|
||||||
// pqevent_queue_sync_event_id(PEVENT_FILE_DOWNLOAD_FINISHED, syncid, name,
|
// pqevent_queue_sync_event_id(PEVENT_FILE_DOWNLOAD_FINISHED, syncid, name,
|
||||||
// fileid);
|
// fileid);
|
||||||
pdbg_logf(D_NOTICE, "file downloaded %s", dt->localname);
|
pdbg_logf(D_NOTICE, "file downloaded %s", dt->localname);
|
||||||
|
pdbg_write_fs_event("file downloaded %s", dt->localname);
|
||||||
psync_list_for_each_element_call(&ranges, psync_range_list_t, list, free);
|
psync_list_for_each_element_call(&ranges, psync_range_list_t, list, free);
|
||||||
if (tmpold) {
|
if (tmpold) {
|
||||||
pfile_delete(tmpold);
|
pfile_delete(tmpold);
|
||||||
|
|
|
||||||
102
pclsync/pfs.c
102
pclsync/pfs.c
|
|
@ -3393,11 +3393,42 @@ void psync_fs_refresh_folder(psync_folderid_t folderid) {
|
||||||
static char *psync_fuse_get_mountpoint() {
|
static char *psync_fuse_get_mountpoint() {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
char *mp;
|
char *mp;
|
||||||
|
int stat_result;
|
||||||
|
int stat_errno;
|
||||||
|
|
||||||
mp = psync_strdup(psync_setting_get_string(_PS(fsroot)));
|
mp = psync_strdup(psync_setting_get_string(_PS(fsroot)));
|
||||||
if (stat(mp, &st) && mkdir(mp, PSYNC_DEFAULT_POSIX_FOLDER_MODE)) {
|
|
||||||
|
stat_result = stat(mp, &st);
|
||||||
|
stat_errno = errno;
|
||||||
|
|
||||||
|
if (stat_result != 0) {
|
||||||
|
/* Provide detailed error message based on errno */
|
||||||
|
if (stat_errno == ENOTCONN) {
|
||||||
|
pdbg_logf(D_CRITICAL,
|
||||||
|
"Mount point %s has a stale FUSE mount (Transport endpoint is not connected). "
|
||||||
|
"Please unmount it first with: fusermount -u %s", mp, mp);
|
||||||
|
} else if (stat_errno == ENOENT) {
|
||||||
|
pdbg_logf(D_CRITICAL,
|
||||||
|
"Mount point %s does not exist. "
|
||||||
|
"Please create the directory first with: mkdir -p %s", mp, mp);
|
||||||
|
} else {
|
||||||
|
pdbg_logf(D_CRITICAL,
|
||||||
|
"Cannot access mount point %s (errno=%d: %s). "
|
||||||
|
"Please verify the path exists and is accessible.",
|
||||||
|
mp, stat_errno, strerror(stat_errno));
|
||||||
|
}
|
||||||
free(mp);
|
free(mp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Verify it's a directory */
|
||||||
|
if (!S_ISDIR(st.st_mode)) {
|
||||||
|
pdbg_logf(D_CRITICAL,
|
||||||
|
"Mount point %s exists but is not a directory", mp);
|
||||||
|
free(mp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return mp;
|
return mp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3438,6 +3469,27 @@ char *psync_fs_get_path_by_folderid(psync_folderid_t folderid) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *psync_fs_get_path_by_fileid(psync_fileid_t fileid) {
|
||||||
|
char *mp, *path, *ret;
|
||||||
|
pthread_mutex_lock(&start_mutex);
|
||||||
|
if (started == 1)
|
||||||
|
mp = psync_strdup(psync_current_mountpoint);
|
||||||
|
else
|
||||||
|
mp = NULL;
|
||||||
|
pthread_mutex_unlock(&start_mutex);
|
||||||
|
if (!mp)
|
||||||
|
return NULL;
|
||||||
|
path = pfolder_file_path(fileid, NULL);
|
||||||
|
if (path == PSYNC_INVALID_PATH) {
|
||||||
|
free(mp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ret = psync_strcat(mp, path, NULL);
|
||||||
|
free(mp);
|
||||||
|
free(path);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#if IS_DEBUG
|
#if IS_DEBUG
|
||||||
|
|
||||||
static void psync_fs_dump_internals() {
|
static void psync_fs_dump_internals() {
|
||||||
|
|
@ -3531,6 +3583,11 @@ static void psync_usr1_handler(int sig) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void psync_usr2_handler(int sig) {
|
||||||
|
/* Signal handler must be signal-safe - just set flag, don't log here */
|
||||||
|
pdbg_reopen_log();
|
||||||
|
}
|
||||||
|
|
||||||
static void psync_set_signal(int sig, void (*handler)(int)) {
|
static void psync_set_signal(int sig, void (*handler)(int)) {
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
|
|
||||||
|
|
@ -3553,6 +3610,7 @@ static void psync_setup_signals() {
|
||||||
#if IS_DEBUG
|
#if IS_DEBUG
|
||||||
psync_set_signal(SIGUSR1, psync_usr1_handler);
|
psync_set_signal(SIGUSR1, psync_usr1_handler);
|
||||||
#endif
|
#endif
|
||||||
|
psync_set_signal(SIGUSR2, psync_usr2_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void psync_fs_init_once() {
|
static void psync_fs_init_once() {
|
||||||
|
|
@ -3632,6 +3690,35 @@ static int psync_fs_do_start() {
|
||||||
}
|
}
|
||||||
fuse_opt_add_arg(&args, "-ohard_remove");
|
fuse_opt_add_arg(&args, "-ohard_remove");
|
||||||
|
|
||||||
|
// Add user-specified FUSE options from environment variable
|
||||||
|
const char *fuse_opts_env = getenv("PCLOUD_FUSE_OPTS");
|
||||||
|
if (fuse_opts_env && fuse_opts_env[0] != '\0') {
|
||||||
|
char *fuse_opts = strdup(fuse_opts_env);
|
||||||
|
if (fuse_opts) {
|
||||||
|
char *saveptr = NULL;
|
||||||
|
char *token = strtok_r(fuse_opts, ",", &saveptr);
|
||||||
|
while (token) {
|
||||||
|
// Trim leading/trailing whitespace
|
||||||
|
while (*token == ' ' || *token == '\t') token++;
|
||||||
|
char *end = token + strlen(token) - 1;
|
||||||
|
while (end > token && (*end == ' ' || *end == '\t')) *end-- = '\0';
|
||||||
|
|
||||||
|
if (strlen(token) > 0) {
|
||||||
|
if (strlen(token) > 250) {
|
||||||
|
pdbg_logf(D_WARNING, "FUSE option too long, skipping: %s", token);
|
||||||
|
} else {
|
||||||
|
char opt_arg[256];
|
||||||
|
snprintf(opt_arg, sizeof(opt_arg), "-o%s", token);
|
||||||
|
fuse_opt_add_arg(&args, opt_arg);
|
||||||
|
pdbg_logf(D_NOTICE, "Adding FUSE option: %s", token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
token = strtok_r(NULL, ",", &saveptr);
|
||||||
|
}
|
||||||
|
free(fuse_opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
memset(&psync_oper, 0, sizeof(psync_oper));
|
memset(&psync_oper, 0, sizeof(psync_oper));
|
||||||
|
|
||||||
psync_oper.init = psync_fs_init;
|
psync_oper.init = psync_fs_init;
|
||||||
|
|
@ -3677,9 +3764,20 @@ static int psync_fs_do_start() {
|
||||||
goto err00;
|
goto err00;
|
||||||
mp = psync_fuse_get_mountpoint();
|
mp = psync_fuse_get_mountpoint();
|
||||||
|
|
||||||
|
if (!mp) {
|
||||||
|
pdbg_logf(D_CRITICAL,
|
||||||
|
"CRITICAL ERROR: Cannot initialize FUSE filesystem. "
|
||||||
|
"Mount point is unavailable. See error messages above for details.");
|
||||||
|
goto err00;
|
||||||
|
}
|
||||||
|
|
||||||
psync_fuse_channel = fuse_mount(mp, &args);
|
psync_fuse_channel = fuse_mount(mp, &args);
|
||||||
if (pdbg_unlikely(!psync_fuse_channel))
|
if (pdbg_unlikely(!psync_fuse_channel)) {
|
||||||
|
pdbg_logf(D_CRITICAL,
|
||||||
|
"CRITICAL ERROR: fuse_mount() failed for mount point %s. "
|
||||||
|
"The FUSE filesystem cannot be started.", mp);
|
||||||
goto err0;
|
goto err0;
|
||||||
|
}
|
||||||
psync_fuse = fuse_new(psync_fuse_channel, &args, &psync_oper,
|
psync_fuse = fuse_new(psync_fuse_channel, &args, &psync_oper,
|
||||||
sizeof(psync_oper), NULL);
|
sizeof(psync_oper), NULL);
|
||||||
if (pdbg_unlikely(!psync_fuse))
|
if (pdbg_unlikely(!psync_fuse))
|
||||||
|
|
|
||||||
|
|
@ -272,19 +272,19 @@ psync_pagecache_get_free_page(int runflushcacheinside) {
|
||||||
} while (flush_page_running && psync_list_isempty(&free_pages));
|
} while (flush_page_running && psync_list_isempty(&free_pages));
|
||||||
}
|
}
|
||||||
if (psync_list_isempty(&free_pages)) {
|
if (psync_list_isempty(&free_pages)) {
|
||||||
pdbg_logf(D_NOTICE, "no free pages, flushing cache");
|
pdbg_logf(D_BUG, "no free pages, flushing cache");
|
||||||
pthread_mutex_unlock(&cache_mutex);
|
pthread_mutex_unlock(&cache_mutex);
|
||||||
flush_pages(1);
|
flush_pages(1);
|
||||||
pthread_mutex_lock(&cache_mutex);
|
pthread_mutex_lock(&cache_mutex);
|
||||||
while (unlikely(psync_list_isempty(&free_pages))) {
|
while (unlikely(psync_list_isempty(&free_pages))) {
|
||||||
pthread_mutex_unlock(&cache_mutex);
|
pthread_mutex_unlock(&cache_mutex);
|
||||||
pdbg_logf(D_NOTICE, "no free pages after flush, sleeping");
|
pdbg_logf(D_BUG, "no free pages after flush, sleeping");
|
||||||
psys_sleep_milliseconds(200);
|
psys_sleep_milliseconds(200);
|
||||||
flush_pages(1);
|
flush_pages(1);
|
||||||
pthread_mutex_lock(&cache_mutex);
|
pthread_mutex_lock(&cache_mutex);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
pdbg_logf(D_NOTICE, "waited for a free page");
|
pdbg_logf(D_BUG, "waited for a free page");
|
||||||
page =
|
page =
|
||||||
psync_list_remove_head_element(&free_pages, psync_cache_page_t, list);
|
psync_list_remove_head_element(&free_pages, psync_cache_page_t, list);
|
||||||
}
|
}
|
||||||
|
|
@ -458,7 +458,7 @@ static int pass_shared_api(psock_t *api) {
|
||||||
shared_api_waiter_t, list);
|
shared_api_waiter_t, list);
|
||||||
waiter->api = api;
|
waiter->api = api;
|
||||||
pthread_cond_signal(&waiter->cond);
|
pthread_cond_signal(&waiter->cond);
|
||||||
pdbg_logf(D_NOTICE, "passing shared api connection");
|
pdbg_logf(D_BUG, "passing shared api connection");
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&sharedapi_mutex);
|
pthread_mutex_unlock(&sharedapi_mutex);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -490,7 +490,7 @@ static int wait_shared_api() {
|
||||||
pthread_cond_init(&waiter->cond, NULL);
|
pthread_cond_init(&waiter->cond, NULL);
|
||||||
waiter->api = NULL;
|
waiter->api = NULL;
|
||||||
psync_list_add_tail(&sharedapiwaiters, &waiter->list);
|
psync_list_add_tail(&sharedapiwaiters, &waiter->list);
|
||||||
pdbg_logf(D_NOTICE, "waiting for shared API connection");
|
pdbg_logf(D_BUG, "waiting for shared API connection");
|
||||||
do {
|
do {
|
||||||
pthread_cond_wait(&waiter->cond, &sharedapi_mutex);
|
pthread_cond_wait(&waiter->cond, &sharedapi_mutex);
|
||||||
} while (!waiter->api);
|
} while (!waiter->api);
|
||||||
|
|
@ -498,7 +498,7 @@ static int wait_shared_api() {
|
||||||
pdbg_assertw(waiter->api == (psock_t *)-1);
|
pdbg_assertw(waiter->api == (psock_t *)-1);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
} else {
|
} else {
|
||||||
pdbg_logf(D_NOTICE, "waited for shared API connection");
|
pdbg_logf(D_BUG, "waited for shared API connection");
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&sharedapi_mutex);
|
pthread_mutex_unlock(&sharedapi_mutex);
|
||||||
|
|
@ -571,7 +571,7 @@ static int get_urls(psync_request_t *request, psync_urls_t *urls) {
|
||||||
totalreqlen = 0;
|
totalreqlen = 0;
|
||||||
psync_list_for_each_element(range, &request->ranges, psync_request_range_t,
|
psync_list_for_each_element(range, &request->ranges, psync_request_range_t,
|
||||||
list) {
|
list) {
|
||||||
pdbg_logf(D_NOTICE, "sending request for offset %lu, size %lu to API",
|
pdbg_logf(D_BUG, "sending request for offset %lu, size %lu to API",
|
||||||
(unsigned long)range->offset, (unsigned long)range->length);
|
(unsigned long)range->offset, (unsigned long)range->length);
|
||||||
if (unlikely(psync_api_send_read_request(api, request->fileid,
|
if (unlikely(psync_api_send_read_request(api, request->fileid,
|
||||||
request->hash, range->offset,
|
request->hash, range->offset,
|
||||||
|
|
@ -595,7 +595,7 @@ static int get_urls(psync_request_t *request, psync_urls_t *urls) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
hosts = papi_find_result2(ret, "hosts", PARAM_ARRAY);
|
hosts = papi_find_result2(ret, "hosts", PARAM_ARRAY);
|
||||||
pdbg_logf(D_NOTICE, "got file URLs of fileid %lu, hash %lu",
|
pdbg_logf(D_BUG, "got file URLs of fileid %lu, hash %lu",
|
||||||
(unsigned long)request->fileid, (unsigned long)request->hash);
|
(unsigned long)request->fileid, (unsigned long)request->hash);
|
||||||
if (pdbg_likely(hosts->length && hosts->array[0]->type == PARAM_STR) &&
|
if (pdbg_likely(hosts->length && hosts->array[0]->type == PARAM_STR) &&
|
||||||
request->of->initialsize > totalreqlen)
|
request->of->initialsize > totalreqlen)
|
||||||
|
|
@ -616,7 +616,7 @@ static int get_urls(psync_request_t *request, psync_urls_t *urls) {
|
||||||
ret);
|
ret);
|
||||||
if (pdbg_unlikely(psync_crypto_is_error(enc)))
|
if (pdbg_unlikely(psync_crypto_is_error(enc)))
|
||||||
goto err4;
|
goto err4;
|
||||||
pdbg_logf(D_NOTICE, "got key for fileid %lu", (unsigned long)request->fileid);
|
pdbg_logf(D_BUG, "got key for fileid %lu", (unsigned long)request->fileid);
|
||||||
free(ret);
|
free(ret);
|
||||||
psync_fs_lock_file(request->of);
|
psync_fs_lock_file(request->of);
|
||||||
if (pdbg_likely(request->of->encoder ==
|
if (pdbg_likely(request->of->encoder ==
|
||||||
|
|
@ -634,7 +634,7 @@ static int get_urls(psync_request_t *request, psync_urls_t *urls) {
|
||||||
if (psync_pagecache_read_range_from_api(request, range, api))
|
if (psync_pagecache_read_range_from_api(request, range, api))
|
||||||
goto err2;
|
goto err2;
|
||||||
psync_list_del(l1);
|
psync_list_del(l1);
|
||||||
pdbg_logf(D_NOTICE, "request for offset %lu, size %lu read from API",
|
pdbg_logf(D_BUG, "request for offset %lu, size %lu read from API",
|
||||||
(unsigned long)range->offset, (unsigned long)range->length);
|
(unsigned long)range->offset, (unsigned long)range->length);
|
||||||
free(range);
|
free(range);
|
||||||
}
|
}
|
||||||
|
|
@ -2452,7 +2452,7 @@ retry:
|
||||||
psock_set_write_buffered(api);
|
psock_set_write_buffered(api);
|
||||||
psync_list_for_each_element(range, &request->ranges,
|
psync_list_for_each_element(range, &request->ranges,
|
||||||
psync_request_range_t, list) {
|
psync_request_range_t, list) {
|
||||||
pdbg_logf(D_NOTICE, "sending request for offset %lu, size %lu to API",
|
pdbg_logf(D_BUG, "sending request for offset %lu, size %lu to API",
|
||||||
(unsigned long)range->offset, (unsigned long)range->length);
|
(unsigned long)range->offset, (unsigned long)range->length);
|
||||||
if (psync_api_send_read_request(api, request->fileid, request->hash,
|
if (psync_api_send_read_request(api, request->fileid, request->hash,
|
||||||
range->offset, range->length))
|
range->offset, range->length))
|
||||||
|
|
@ -2856,10 +2856,10 @@ static void wait_waiter(psync_page_waiter_t *pwt, uint64_t hash,
|
||||||
const char *pt) {
|
const char *pt) {
|
||||||
lock_wait(hash);
|
lock_wait(hash);
|
||||||
while (!pwt->ready) {
|
while (!pwt->ready) {
|
||||||
pdbg_logf(D_NOTICE, "waiting for %s page #%lu to be read", pt,
|
pdbg_logf(D_BUG, "waiting for %s page #%lu to be read", pt,
|
||||||
(unsigned long)pwt->waiting_for->pageid);
|
(unsigned long)pwt->waiting_for->pageid);
|
||||||
pthread_cond_wait(&pwt->cond, &wait_page_mutex);
|
pthread_cond_wait(&pwt->cond, &wait_page_mutex);
|
||||||
pdbg_logf(D_NOTICE, "waited for %s page",
|
pdbg_logf(D_BUG, "waited for %s page",
|
||||||
pt); // not safe to use pwt->waiting_for here
|
pt); // not safe to use pwt->waiting_for here
|
||||||
}
|
}
|
||||||
unlock_wait(hash);
|
unlock_wait(hash);
|
||||||
|
|
|
||||||
|
|
@ -242,8 +242,12 @@ void psql_do_lock(const char *file, unsigned line) {
|
||||||
clock_gettime(CLOCK_REALTIME, &end);
|
clock_gettime(CLOCK_REALTIME, &end);
|
||||||
msec = (end.tv_sec - start.tv_sec) * 1000 + end.tv_nsec / 1000000 -
|
msec = (end.tv_sec - start.tv_sec) * 1000 + end.tv_nsec / 1000000 -
|
||||||
start.tv_nsec / 1000000;
|
start.tv_nsec / 1000000;
|
||||||
if (msec >= 5)
|
if (msec >= 1000)
|
||||||
|
pdbg_logf(D_ERROR, "waited %lu milliseconds for database write lock", msec);
|
||||||
|
else if (msec >= 250)
|
||||||
pdbg_logf(D_WARNING, "waited %lu milliseconds for database write lock", msec);
|
pdbg_logf(D_WARNING, "waited %lu milliseconds for database write lock", msec);
|
||||||
|
else if (msec >= 5)
|
||||||
|
pdbg_logf(D_BUG, "waited %lu milliseconds for database write lock", msec);
|
||||||
pdbg_assert(lockctr == 0);
|
pdbg_assert(lockctr == 0);
|
||||||
lockctr++;
|
lockctr++;
|
||||||
memcpy(&lockstart, &end, sizeof(struct timespec));
|
memcpy(&lockstart, &end, sizeof(struct timespec));
|
||||||
|
|
@ -270,8 +274,12 @@ void psql_do_rdlock(const char *file, unsigned line) {
|
||||||
clock_gettime(CLOCK_REALTIME, &end);
|
clock_gettime(CLOCK_REALTIME, &end);
|
||||||
msec = (end.tv_sec - start.tv_sec) * 1000 + end.tv_nsec / 1000000 -
|
msec = (end.tv_sec - start.tv_sec) * 1000 + end.tv_nsec / 1000000 -
|
||||||
start.tv_nsec / 1000000;
|
start.tv_nsec / 1000000;
|
||||||
if (msec >= 5)
|
if (msec >= 1000)
|
||||||
|
pdbg_logf(D_ERROR, "waited %lu milliseconds for database read lock", msec);
|
||||||
|
else if (msec >= 250)
|
||||||
pdbg_logf(D_WARNING, "waited %lu milliseconds for database read lock", msec);
|
pdbg_logf(D_WARNING, "waited %lu milliseconds for database read lock", msec);
|
||||||
|
else if (msec >= 5)
|
||||||
|
pdbg_logf(D_BUG, "waited %lu milliseconds for database read lock", msec);
|
||||||
rdlockctr++;
|
rdlockctr++;
|
||||||
memcpy(&rdlockstart, &end, sizeof(struct timespec));
|
memcpy(&rdlockstart, &end, sizeof(struct timespec));
|
||||||
record_rdlock(file, line, &rdlockstart);
|
record_rdlock(file, line, &rdlockstart);
|
||||||
|
|
@ -430,10 +438,18 @@ void psql_unlock() {
|
||||||
clock_gettime(CLOCK_REALTIME, &end);
|
clock_gettime(CLOCK_REALTIME, &end);
|
||||||
msec = (end.tv_sec - lockstart.tv_sec) * 1000 + end.tv_nsec / 1000000 -
|
msec = (end.tv_sec - lockstart.tv_sec) * 1000 + end.tv_nsec / 1000000 -
|
||||||
lockstart.tv_nsec / 1000000;
|
lockstart.tv_nsec / 1000000;
|
||||||
if (msec >= 10)
|
if (msec >= 2000)
|
||||||
|
pdbg_logf(D_ERROR,
|
||||||
|
"held database write lock for %lu milliseconds taken from %s:%u",
|
||||||
|
msec, wrlockfile, wrlockline);
|
||||||
|
else if (msec >= 500)
|
||||||
pdbg_logf(D_WARNING,
|
pdbg_logf(D_WARNING,
|
||||||
"held database write lock for %lu milliseconds taken from %s:%u",
|
"held database write lock for %lu milliseconds taken from %s:%u",
|
||||||
msec, wrlockfile, wrlockline);
|
msec, wrlockfile, wrlockline);
|
||||||
|
else if (msec >= 10)
|
||||||
|
pdbg_logf(D_BUG,
|
||||||
|
"held database write lock for %lu milliseconds taken from %s:%u",
|
||||||
|
msec, wrlockfile, wrlockline);
|
||||||
record_wrunlock();
|
record_wrunlock();
|
||||||
plocks_unlock(&dblock);
|
plocks_unlock(&dblock);
|
||||||
} else
|
} else
|
||||||
|
|
@ -487,10 +503,18 @@ void psql_rdunlock() {
|
||||||
lock = record_rdunlock();
|
lock = record_rdunlock();
|
||||||
msec = (end.tv_sec - rdlockstart.tv_sec) * 1000 + end.tv_nsec / 1000000 -
|
msec = (end.tv_sec - rdlockstart.tv_sec) * 1000 + end.tv_nsec / 1000000 -
|
||||||
rdlockstart.tv_nsec / 1000000;
|
rdlockstart.tv_nsec / 1000000;
|
||||||
if (msec >= 20)
|
if (msec >= 2000)
|
||||||
|
pdbg_logf(D_ERROR,
|
||||||
|
"held database read lock for %lu milliseconds taken at %s:%u", msec,
|
||||||
|
lock->file, lock->line);
|
||||||
|
else if (msec >= 500)
|
||||||
pdbg_logf(D_WARNING,
|
pdbg_logf(D_WARNING,
|
||||||
"held database read lock for %lu milliseconds taken at %s:%u", msec,
|
"held database read lock for %lu milliseconds taken at %s:%u", msec,
|
||||||
lock->file, lock->line);
|
lock->file, lock->line);
|
||||||
|
else if (msec >= 20)
|
||||||
|
pdbg_logf(D_BUG,
|
||||||
|
"held database read lock for %lu milliseconds taken at %s:%u", msec,
|
||||||
|
lock->file, lock->line);
|
||||||
free(lock);
|
free(lock);
|
||||||
} else
|
} else
|
||||||
plocks_unlock(&dblock);
|
plocks_unlock(&dblock);
|
||||||
|
|
|
||||||
|
|
@ -343,8 +343,8 @@ int pssl_connect(int sock, void **sslconn,
|
||||||
goto err0;
|
goto err0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mbedtls_ssl_conf_max_tls_version(&conn->cfg, MBEDTLS_SSL_VERSION_TLS1_2);
|
mbedtls_ssl_conf_max_version(&conn->cfg, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
|
||||||
mbedtls_ssl_conf_min_tls_version(&conn->cfg, MBEDTLS_SSL_VERSION_TLS1_2);
|
mbedtls_ssl_conf_min_version(&conn->cfg, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
|
||||||
|
|
||||||
mbedtls_ssl_conf_endpoint(&conn->cfg, MBEDTLS_SSL_IS_CLIENT);
|
mbedtls_ssl_conf_endpoint(&conn->cfg, MBEDTLS_SSL_IS_CLIENT);
|
||||||
mbedtls_ssl_conf_dbg(&conn->cfg, debug_cb, debug_ctx);
|
mbedtls_ssl_conf_dbg(&conn->cfg, debug_cb, debug_ctx);
|
||||||
|
|
@ -673,13 +673,12 @@ psymkey_generate(const char *password, size_t keylen,
|
||||||
keylen + offsetof(psync_symmetric_key_struct_t, key));
|
keylen + offsetof(psync_symmetric_key_struct_t, key));
|
||||||
mbedtls_md_context_t ctx;
|
mbedtls_md_context_t ctx;
|
||||||
mbedtls_md_init(&ctx);
|
mbedtls_md_init(&ctx);
|
||||||
mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), 1);
|
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
|
||||||
|
mbedtls_md_setup(&ctx, md_info, 1);
|
||||||
key->keylen = keylen;
|
key->keylen = keylen;
|
||||||
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_ctx(&ctx);
|
mbedtls_pkcs5_pbkdf2_hmac(&ctx, (const unsigned char *)password,
|
||||||
mbedtls_md_type_t md_type = mbedtls_md_get_type(md_info);
|
strlen(password), salt, saltlen, iterations,
|
||||||
mbedtls_pkcs5_pbkdf2_hmac_ext(md_type, (const unsigned char *)password,
|
keylen, key->key);
|
||||||
strlen(password), salt, saltlen, iterations, keylen,
|
|
||||||
key->key);
|
|
||||||
mbedtls_md_free(&ctx);
|
mbedtls_md_free(&ctx);
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
@ -700,10 +699,9 @@ char *psymkey_derive(const char *username,
|
||||||
psync_sha512(usercopy, userlen, usersha512);
|
psync_sha512(usercopy, userlen, usersha512);
|
||||||
free(usercopy);
|
free(usercopy);
|
||||||
mbedtls_md_init(&ctx);
|
mbedtls_md_init(&ctx);
|
||||||
mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), 1);
|
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
|
||||||
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_ctx(&ctx);
|
mbedtls_md_setup(&ctx, md_info, 1);
|
||||||
mbedtls_md_type_t md_type = mbedtls_md_get_type(md_info);
|
mbedtls_pkcs5_pbkdf2_hmac(&ctx, (const unsigned char *)passphrase, strlen(passphrase), usersha512,
|
||||||
mbedtls_pkcs5_pbkdf2_hmac_ext(md_type, (const unsigned char *)passphrase, strlen(passphrase), usersha512,
|
|
||||||
PSYNC_SHA512_DIGEST_LEN, 5000, sizeof(passwordbin), passwordbin);
|
PSYNC_SHA512_DIGEST_LEN, 5000, sizeof(passwordbin), passwordbin);
|
||||||
mbedtls_md_free(&ctx);
|
mbedtls_md_free(&ctx);
|
||||||
usercopy = psync_base64_encode(passwordbin, sizeof(passwordbin), &userlen);
|
usercopy = psync_base64_encode(passwordbin, sizeof(passwordbin), &userlen);
|
||||||
|
|
@ -741,8 +739,8 @@ psync_symmetric_key_t prsa_decrypt_data(psync_rsa_privatekey_t rsa,
|
||||||
psync_symmetric_key_t ret;
|
psync_symmetric_key_t ret;
|
||||||
size_t len;
|
size_t len;
|
||||||
if (mbedtls_rsa_rsaes_oaep_decrypt(rsa, rng_get,
|
if (mbedtls_rsa_rsaes_oaep_decrypt(rsa, rng_get,
|
||||||
&rng, NULL,
|
&rng,
|
||||||
0, &len, data, buff, sizeof(buff)))
|
NULL, 0, &len, data, buff, sizeof(buff)))
|
||||||
return PSYNC_INVALID_SYM_KEY;
|
return PSYNC_INVALID_SYM_KEY;
|
||||||
ret = (psync_symmetric_key_t)malloc(
|
ret = (psync_symmetric_key_t)malloc(
|
||||||
offsetof(psync_symmetric_key_struct_t, key) + len);
|
offsetof(psync_symmetric_key_struct_t, key) + len);
|
||||||
|
|
@ -803,6 +801,7 @@ prsa_sign_sha256_hash(psync_rsa_privatekey_t rsa,
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return (psync_rsa_signature_t)(void *)PERROR_NO_MEMORY;
|
return (psync_rsa_signature_t)(void *)PERROR_NO_MEMORY;
|
||||||
ret->datalen = rsalen;
|
ret->datalen = rsalen;
|
||||||
|
/* Save current padding settings using getter functions */
|
||||||
padding = mbedtls_rsa_get_padding_mode(rsa);
|
padding = mbedtls_rsa_get_padding_mode(rsa);
|
||||||
hash_id = mbedtls_rsa_get_md_alg(rsa);
|
hash_id = mbedtls_rsa_get_md_alg(rsa);
|
||||||
mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
|
mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
|
||||||
|
|
|
||||||
|
|
@ -1158,6 +1158,7 @@ void psync_fs_stop();
|
||||||
char *psync_fs_getmountpoint();
|
char *psync_fs_getmountpoint();
|
||||||
void psync_fs_register_start_callback(psync_generic_callback_t callback);
|
void psync_fs_register_start_callback(psync_generic_callback_t callback);
|
||||||
char *psync_fs_get_path_by_folderid(psync_folderid_t folderid);
|
char *psync_fs_get_path_by_folderid(psync_folderid_t folderid);
|
||||||
|
char *psync_fs_get_path_by_fileid(psync_fileid_t fileid);
|
||||||
|
|
||||||
void psync_fs_clean_read_cache();
|
void psync_fs_clean_read_cache();
|
||||||
int psync_fs_move_cache(const char *path);
|
int psync_fs_move_cache(const char *path);
|
||||||
|
|
|
||||||
|
|
@ -275,8 +275,12 @@ unsigned char *psync_base64_encode(const unsigned char *str, size_t length,
|
||||||
if (length > 1) {
|
if (length > 1) {
|
||||||
*p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
|
*p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];
|
||||||
*p++ = base64_table[(current[1] & 0x0f) << 2];
|
*p++ = base64_table[(current[1] & 0x0f) << 2];
|
||||||
} else
|
*p++ = '='; /* Add padding */
|
||||||
|
} else {
|
||||||
*p++ = base64_table[(current[0] & 0x03) << 4];
|
*p++ = base64_table[(current[0] & 0x03) << 4];
|
||||||
|
*p++ = '='; /* Add padding */
|
||||||
|
*p++ = '='; /* Add padding */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*ret_length = p - result;
|
*ret_length = p - result;
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,9 @@
|
||||||
#include "pclsync/pdevice.h"
|
#include "pclsync/pdevice.h"
|
||||||
#include "pclsync/pcommands.h"
|
#include "pclsync/pcommands.h"
|
||||||
#include "pclsync/putil.h"
|
#include "pclsync/putil.h"
|
||||||
|
#include "pclsync/pdbg.h"
|
||||||
|
#include "pclsync/psock.h"
|
||||||
|
#include "pclsync/plibs.h"
|
||||||
|
|
||||||
#include "pclsync_lib.h"
|
#include "pclsync_lib.h"
|
||||||
|
|
||||||
|
|
@ -56,6 +59,47 @@ static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
static const std::string client_name = "pCloud CC v3.0.0";
|
static const std::string client_name = "pCloud CC v3.0.0";
|
||||||
|
|
||||||
|
static const char *psync_error_to_string(uint32_t error_code) {
|
||||||
|
switch (error_code) {
|
||||||
|
case PERROR_LOCAL_FOLDER_NOT_FOUND:
|
||||||
|
return "local folder not found";
|
||||||
|
case PERROR_REMOTE_FOLDER_NOT_FOUND:
|
||||||
|
return "remote folder not found";
|
||||||
|
case PERROR_DATABASE_OPEN:
|
||||||
|
return "failed to open database";
|
||||||
|
case PERROR_NO_HOMEDIR:
|
||||||
|
return "cannot determine home directory or create .pcloud directory";
|
||||||
|
case PERROR_SSL_INIT_FAILED:
|
||||||
|
return "SSL initialization failed";
|
||||||
|
case PERROR_DATABASE_ERROR:
|
||||||
|
return "database error";
|
||||||
|
case PERROR_LOCAL_FOLDER_ACC_DENIED:
|
||||||
|
return "local folder access denied";
|
||||||
|
case PERROR_REMOTE_FOLDER_ACC_DENIED:
|
||||||
|
return "remote folder access denied";
|
||||||
|
case PERROR_FOLDER_ALREADY_SYNCING:
|
||||||
|
return "folder already syncing";
|
||||||
|
case PERROR_INVALID_SYNCTYPE:
|
||||||
|
return "invalid sync type";
|
||||||
|
case PERROR_OFFLINE:
|
||||||
|
return "offline";
|
||||||
|
case PERROR_INVALID_SYNCID:
|
||||||
|
return "invalid sync ID";
|
||||||
|
case PERROR_PARENT_OR_SUBFOLDER_ALREADY_SYNCING:
|
||||||
|
return "parent or subfolder already syncing";
|
||||||
|
case PERROR_LOCAL_IS_ON_PDRIVE:
|
||||||
|
return "local path is on pCloud Drive";
|
||||||
|
case PERROR_NO_MEMORY:
|
||||||
|
return "out of memory";
|
||||||
|
case PERROR_NET_ERROR:
|
||||||
|
return "network error";
|
||||||
|
case PERROR_PARENT_IS_IGNORED:
|
||||||
|
return "parent folder is ignored";
|
||||||
|
default:
|
||||||
|
return "unknown error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
clib::pclsync_lib::pclsync_lib()
|
clib::pclsync_lib::pclsync_lib()
|
||||||
: setup_crypto_(false), status_(new pstatus_struct_()), was_init_(false) {}
|
: setup_crypto_(false), status_(new pstatus_struct_()), was_init_(false) {}
|
||||||
|
|
||||||
|
|
@ -96,6 +140,9 @@ void clib::pclsync_lib::set_tfa_code(const std::string &arg) {
|
||||||
void clib::pclsync_lib::set_username(const std::string &arg) {
|
void clib::pclsync_lib::set_username(const std::string &arg) {
|
||||||
username_ = arg;
|
username_ = arg;
|
||||||
}
|
}
|
||||||
|
void clib::pclsync_lib::set_password(const std::string &arg) {
|
||||||
|
password_ = arg;
|
||||||
|
}
|
||||||
void clib::pclsync_lib::set_crypto_pass(const std::string &arg) {
|
void clib::pclsync_lib::set_crypto_pass(const std::string &arg) {
|
||||||
crypto_pass_ = arg;
|
crypto_pass_ = arg;
|
||||||
};
|
};
|
||||||
|
|
@ -499,7 +546,8 @@ int clib::pclsync_lib::init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (psync_init()) {
|
if (psync_init()) {
|
||||||
std::cout << "init failed\n";
|
std::cerr << "Initialization failed: " << psync_error_to_string(psync_error)
|
||||||
|
<< " (error code: " << psync_error << ")" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -509,6 +557,16 @@ int clib::pclsync_lib::init() {
|
||||||
psync_set_string_setting("fsroot", get_mount().c_str());
|
psync_set_string_setting("fsroot", get_mount().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *cache_size_env = getenv("PCLOUD_CACHE_SIZE");
|
||||||
|
if (cache_size_env && cache_size_env[0] != '\0') {
|
||||||
|
try {
|
||||||
|
uint64_t cache_size = std::stoull(cache_size_env);
|
||||||
|
psync_set_uint_setting("fscachesize", cache_size);
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
pdbg_logf(D_ERROR, "Invalid PCLOUD_CACHE_SIZE: %s", cache_size_env);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
psync_start_sync(status_change, event_handler);
|
psync_start_sync(status_change, event_handler);
|
||||||
|
|
||||||
username_old = psync_get_username();
|
username_old = psync_get_username();
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ public:
|
||||||
void set_trusted_device(bool arg);
|
void set_trusted_device(bool arg);
|
||||||
void set_tfa_code(const std::string& arg);
|
void set_tfa_code(const std::string& arg);
|
||||||
void set_username(const std::string &arg);
|
void set_username(const std::string &arg);
|
||||||
|
void set_password(const std::string &arg);
|
||||||
void set_crypto_pass(const std::string &arg);
|
void set_crypto_pass(const std::string &arg);
|
||||||
void set_mount(const std::string &arg);
|
void set_mount(const std::string &arg);
|
||||||
void set_savepass(bool s);
|
void set_savepass(bool s);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue