Migrate to FUSE 3.x API (#350)
* Migrate to FUSE 3.x API - Update FUSE_USE_VERSION from 26 to 30 - Replace fuse_mount/fuse_unmount with fuse_session_mount/fuse_session_unmount - Update fuse_new() to take args first, remove channel parameter - Add flags parameter to readdir handler (enum fuse_readdir_flags) - Add flags parameter to rename handler (for renameat2 support) - Update filler function calls to include FUSE_FILL_DIR_PLUS flag - Merge ftruncate into truncate handler (FUSE 3 combines them) - Update fuse_loop_mt to fuse_loop_mt_31 with loop config - Link against libfuse3 instead of libfuse - Remove fuse_chan usage (deprecated in FUSE 3) Addresses #342 * Remove deprecated FUSE options nonempty and hard_remove - nonempty: Removed in FUSE 3.0, mounting on non-empty directories is now default behavior - hard_remove: High-level API option not available in FUSE 3, immediate unlink is standard These options are no longer recognized by FUSE 3 and cause mount errors. * Fix init handler signature for FUSE 3 FUSE 3 init handler requires struct fuse_config* parameter. This parameter provides access to high-level API configuration options that can be modified during initialization. Without this parameter, the init handler signature is incompatible with FUSE 3, causing filesystem operations to fail. * Add FUSE 2/3 backward compatibility Automatically detects and builds against either FUSE 2 or FUSE 3: - detect_fuse.sh script checks for fuse3 or fuse pkg-config - Makefile dynamically sets FUSE_USE_VERSION, CFLAGS, and LDFLAGS - Conditional compilation (#if FUSE_USE_VERSION >= 30) for API differences: * init handler signature (fuse_config parameter) * readdir handler signature (flags parameter) * rename handler signature (flags parameter) * truncate handler signature (fuse_file_info parameter) * filler function calls (flags parameter) * fuse_loop_mt vs fuse_loop_mt_31 * mount/unmount sequence (fuse_session_mount vs fuse_mount) * ftruncate operations struct member Maintains full compatibility with both FUSE 2.x (Debian Bookworm) and FUSE 3.x (Debian Testing+) without requiring separate code branches. * Add FORCE_FUSE build option and fix hardcoded version - Remove hardcoded FUSE_USE_VERSION defines from source files - Add FORCE_FUSE=2 or FORCE_FUSE=3 Makefile option to override detection - Fix FUSE 2 channel tracking (psync_fuse_channel variable) - Properly store and use channel in mount/unmount for FUSE 2 Usage: make # Auto-detect (prefers FUSE 3) make FORCE_FUSE=2 # Force FUSE 2 build make FORCE_FUSE=3 # Force FUSE 3 build Verified both FUSE 2 and FUSE 3 builds work correctly. * Fix CI/CD: Add fallback for systems without pkg-config - detect_fuse.sh now checks for pkg-config availability first - Falls back to checking for header files in standard locations - Makefile provides default CFLAGS when pkg-config unavailable - Fixes build on minimal CI/CD environments Fallback locations checked: - /usr/include/fuse3/fuse.h (FUSE 3) - /usr/local/include/fuse3/fuse.h (FUSE 3) - /usr/include/fuse/fuse.h (FUSE 2) - /usr/local/include/fuse/fuse.h (FUSE 2) * Enhance FUSE detection for non-standard locations Multi-stage detection strategy: 1. Try pkg-config (fastest, most reliable) 2. Search common header locations: - /usr/include, /usr/local/include - /opt/local/include, /opt/include 3. Compiler test as last resort: - Attempts to preprocess #include <fuse.h> - Tests both FUSE 3 and FUSE 2 versions This handles: - Minimal CI/CD environments (no pkg-config) - Non-standard install locations (Homebrew, custom builds) - Distro-specific paths (BSD, macOS, custom Linux) The compiler test ensures detection works even when headers are in unusual locations that gcc can find via its search paths. * Support FUSE 3.12+ API - Use fuse_loop_mt_312 for FUSE 3.12+, fuse_loop_mt_31 for 3.0-3.11 - Conditionally add fuse_file_info param to getattr/chmod/chown/utimens - Replace fuse_session_mount/unmount with fuse_mount/unmount - Tested with FUSE 3.18 on Debian forky * Fix pcl-1ib: correct FUSE 3.x handler signatures and loop_mt call - Replace FUSE_MINOR_VERSION >= 12 checks with FUSE_USE_VERSION >= 30 for getattr/chmod/chown/utimens handler signatures; FUSE 3.x always requires the extra struct fuse_file_info* parameter — the wrong signature caused type mismatches and "Transport endpoint is not connected" failures - Replace non-existent fuse_loop_mt_312 extern with correct conditional: FUSE_USE_VERSION >= 32 uses fuse_loop_mt(f, &config), else fuse_loop_mt_31(f, clone_fd) - Fix inverted return logic in is_fuse3_installed_on_system(): was returning 0 on success (when fusermount3 found), now correctly returns non-zero Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Remove unused is_fuse3_installed_on_system() from pfs.c The function was static and had no remaining call sites after the -ononempty/-ohard_remove args block was cleaned up, producing a -Wunused-function warning. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Restore shutdown_requested definition removed during rebase conflict resolution The variable is declared extern in pfs.h and referenced in both pfs.c (psync_signal_handler) and control_tools.cpp; the definition must exist in pfs.c. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix pfs_creat: missing canmodify assignment causes EACCES on write pfs_creat called pfs_create_file() but never set of->canmodify, leaving it zero-initialized. pfs_write and pfs_ftruncate both check canmodify and return -EACCES if false, making all writes to newly created files fail with Permission denied. All five open paths in pfs_open set canmodify correctly (added in #326), but pfs_creat was missed. Fix by applying the same pattern immediately after psql_unlock(), while fpath is still in scope. Caught during FUSE 2/3 regression testing (Phase 2 write test). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Extend CI matrix: add FUSE 2, FUSE 3 legacy/current/forky build jobs Replaces single build job with four jobs covering all tested FUSE configs: - fuse2: debian:trixie + libfuse-dev (FUSE_USE_VERSION=26) - fuse3-legacy: ubuntu:20.04 + libfuse3-dev 3.9.x (fuse_loop_mt_31 path) - fuse3-current: ubuntu:22.04 + libfuse3-dev 3.12.x - fuse3-forky: debian:forky + libfuse3-dev 3.18.1 Each job verifies correct symbol linkage after build. Runtime mount tests are outside CI scope (require privileged containers with /dev/fuse). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * CI: replace Ubuntu 20.04/22.04 with ubuntu:24.04 for FUSE3 job ubuntu:20.04 has old compiler (g++-9) and mbedTLS 2.x. ubuntu:22.04 ships mbedTLS 2.28.x; incompatible with our mbedTLS 3.x-only code. ubuntu:24.04 has mbedTLS 3.x and libfuse3 3.16.x, covering the 3.12-3.17 range. FUSE3 < 3.12 is verified locally but not representable in CI without fighting old toolchains. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * CI: add archlinux:latest job for rolling-release compatibility Arch Linux is a rolling distro shipping latest fuse3, mbedtls 3.x, and gcc — useful as an early-warning canary for future API breakage. Also directly covers the maintained Arch package. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * CI: add fedora:41 and fedora:latest jobs with mbedtls3-devel Fedora ships both mbedtls 2.x and 3.x; explicitly install mbedtls3-devel to match our mbedTLS 3.x-only requirement. fedora:41 pins a known-good release; fedora:latest tracks current as a rolling canary alongside Arch. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * README: add compatibility matrix with CI badge references Documents the 6-distro build matrix tested in CI, mbedTLS 3.x requirement, and notes on manual runtime mount testing coverage. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix CI package names; clean up README compatibility matrix - Fedora 41: mbedtls3-devel -> mbedtls3.6-devel (correct versioned name) - Fedora latest (43): mbedtls3-devel -> mbedtls-devel (now ships 3.6.5) - Ubuntu 24.04: replaced with debian:trixie FORCE_FUSE=3 (Ubuntu has no mbedTLS 3.x in standard repos; trixie has both libfuse3-dev and mbedTLS 3.x) - README: remove CI badge links from compatibility matrix Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Levi Neely <lkn@darkstar.example.net> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
90945b8817
commit
0c0c6855c1
|
|
@ -7,7 +7,8 @@ on:
|
||||||
branches: [ "main" ]
|
branches: [ "main" ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
fuse2:
|
||||||
|
name: FUSE 2 (debian:trixie)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: debian:trixie
|
image: debian:trixie
|
||||||
|
|
@ -16,6 +17,108 @@ jobs:
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get install -y build-essential libreadline-dev libudev-dev libfuse-dev libsqlite3-dev zlib1g-dev libboost-dev libboost-system-dev libboost-program-options-dev libmbedtls-dev
|
apt-get install -y build-essential pkg-config libreadline-dev libudev-dev \
|
||||||
- name: make
|
libfuse-dev libsqlite3-dev zlib1g-dev \
|
||||||
run: make
|
libboost-dev libboost-program-options-dev libmbedtls-dev
|
||||||
|
- name: Build (FUSE 2)
|
||||||
|
run: make FORCE_FUSE=2 BUILD=release
|
||||||
|
- name: Verify symbols
|
||||||
|
run: |
|
||||||
|
nm pcloudcc | grep -E 'fuse_loop_mt@|fuse_mount@|psync_fuse_channel'
|
||||||
|
ldd pcloudcc | grep libfuse.so.2
|
||||||
|
|
||||||
|
fuse3-current:
|
||||||
|
name: FUSE 3 current (debian:trixie)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: debian:trixie
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y build-essential pkg-config libreadline-dev libudev-dev \
|
||||||
|
libfuse3-dev libsqlite3-dev zlib1g-dev \
|
||||||
|
libboost-dev libboost-program-options-dev libmbedtls-dev
|
||||||
|
- name: Build (FUSE 3 current)
|
||||||
|
run: make FORCE_FUSE=3 BUILD=release
|
||||||
|
- name: Verify symbols
|
||||||
|
run: |
|
||||||
|
nm pcloudcc | grep 'fuse_loop_mt_31'
|
||||||
|
ldd pcloudcc | grep libfuse3
|
||||||
|
|
||||||
|
fuse3-arch:
|
||||||
|
name: FUSE 3 rolling (archlinux:latest)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: archlinux:latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
pacman -Sy --noconfirm base-devel pkg-config readline fuse3 sqlite3 \
|
||||||
|
zlib boost mbedtls
|
||||||
|
- name: Build (FUSE 3 rolling)
|
||||||
|
run: make FORCE_FUSE=3 BUILD=release
|
||||||
|
- name: Verify symbols
|
||||||
|
run: |
|
||||||
|
nm pcloudcc | grep 'fuse_loop_mt'
|
||||||
|
ldd pcloudcc | grep libfuse3
|
||||||
|
|
||||||
|
fuse3-fedora41:
|
||||||
|
name: FUSE 3 (fedora:41)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: fedora:41
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
dnf install -y gcc gcc-c++ make pkg-config binutils \
|
||||||
|
readline-devel systemd-devel fuse3-devel sqlite-devel zlib-devel \
|
||||||
|
boost-devel boost-program-options mbedtls3.6-devel
|
||||||
|
- name: Build (FUSE 3 Fedora 41)
|
||||||
|
run: make FORCE_FUSE=3 BUILD=release
|
||||||
|
- name: Verify symbols
|
||||||
|
run: |
|
||||||
|
nm pcloudcc | grep 'fuse_loop_mt'
|
||||||
|
ldd pcloudcc | grep libfuse3
|
||||||
|
|
||||||
|
fuse3-fedora-latest:
|
||||||
|
name: FUSE 3 (fedora:latest)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: fedora:latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
dnf install -y gcc gcc-c++ make pkg-config binutils \
|
||||||
|
readline-devel systemd-devel fuse3-devel sqlite-devel zlib-devel \
|
||||||
|
boost-devel boost-program-options mbedtls-devel
|
||||||
|
- name: Build (FUSE 3 Fedora latest)
|
||||||
|
run: make FORCE_FUSE=3 BUILD=release
|
||||||
|
- name: Verify symbols
|
||||||
|
run: |
|
||||||
|
nm pcloudcc | grep 'fuse_loop_mt'
|
||||||
|
ldd pcloudcc | grep libfuse3
|
||||||
|
|
||||||
|
fuse3-forky:
|
||||||
|
name: FUSE 3.18+ (debian:forky)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: debian:forky
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y build-essential pkg-config libreadline-dev libudev-dev \
|
||||||
|
libfuse3-dev libsqlite3-dev zlib1g-dev \
|
||||||
|
libboost-dev libboost-program-options-dev libmbedtls-dev
|
||||||
|
- name: Build (FUSE 3.18+)
|
||||||
|
run: make FORCE_FUSE=3 BUILD=release
|
||||||
|
- name: Verify symbols
|
||||||
|
run: |
|
||||||
|
nm pcloudcc | grep 'fuse_loop_mt_31'
|
||||||
|
ldd pcloudcc | grep libfuse3
|
||||||
|
|
|
||||||
37
Makefile
37
Makefile
|
|
@ -5,8 +5,33 @@ AR := ar
|
||||||
DIST_CFLAGS := $(CFLAGS)
|
DIST_CFLAGS := $(CFLAGS)
|
||||||
DIST_CXXFLAGS := $(CXXFLAGS)
|
DIST_CXXFLAGS := $(CXXFLAGS)
|
||||||
|
|
||||||
|
# Detect FUSE version (can be overridden with FORCE_FUSE=2 or FORCE_FUSE=3)
|
||||||
|
ifdef FORCE_FUSE
|
||||||
|
ifeq ($(FORCE_FUSE),2)
|
||||||
|
FUSE_VERSION := FUSE2
|
||||||
|
else ifeq ($(FORCE_FUSE),3)
|
||||||
|
FUSE_VERSION := FUSE3
|
||||||
|
else
|
||||||
|
$(error FORCE_FUSE must be 2 or 3)
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
FUSE_VERSION := $(shell ./detect_fuse.sh)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(FUSE_VERSION),FUSE3)
|
||||||
|
FUSE_CFLAGS := $(shell pkg-config --cflags fuse3 2>/dev/null || echo "-I/usr/include/fuse3 -D_FILE_OFFSET_BITS=64")
|
||||||
|
FUSE_LIBS := -lfuse3
|
||||||
|
FUSE_USE_VERSION := 30
|
||||||
|
else ifeq ($(FUSE_VERSION),FUSE2)
|
||||||
|
FUSE_CFLAGS := $(shell pkg-config --cflags fuse 2>/dev/null || echo "-I/usr/include/fuse -D_FILE_OFFSET_BITS=64")
|
||||||
|
FUSE_LIBS := -lfuse
|
||||||
|
FUSE_USE_VERSION := 26
|
||||||
|
else
|
||||||
|
$(error FUSE library not found. Install libfuse-dev or libfuse3-dev)
|
||||||
|
endif
|
||||||
|
|
||||||
COMMONFLAGS = -fsanitize=address
|
COMMONFLAGS = -fsanitize=address
|
||||||
CFLAGS = -fPIC $(COMMONFLAGS) -I./pclsync -I/usr/include $(shell pkg-config --cflags $$(pkg-config --list-all | grep -o 'mbedtls[0-9.]*\s' | head -1) 2>/dev/null || pkg-config --cflags mbedtls 2>/dev/null || echo "-I/usr/local/include")
|
CFLAGS = -fPIC $(COMMONFLAGS) -I./pclsync -I/usr/include $(FUSE_CFLAGS) $(shell pkg-config --cflags $$(pkg-config --list-all | grep -o 'mbedtls[0-9.]*\s' | head -1) 2>/dev/null || pkg-config --cflags mbedtls 2>/dev/null || echo "-I/usr/local/include")
|
||||||
ifneq (,$(filter clang%,$(CC)))
|
ifneq (,$(filter clang%,$(CC)))
|
||||||
CFLAGS += -Wthread-safety
|
CFLAGS += -Wthread-safety
|
||||||
endif
|
endif
|
||||||
|
|
@ -20,7 +45,7 @@ LIBLDFLAGS = $(COMMONFLAGS) -lreadline -lpthread -ludev -lsqlite3 -lz $(shell \
|
||||||
else \
|
else \
|
||||||
pkg-config --libs mbedtls mbedx509 mbedcrypto 2>/dev/null || echo "-L/usr/local/lib -lmbedtls -lmbedx509 -lmbedcrypto"; \
|
pkg-config --libs mbedtls mbedx509 mbedcrypto 2>/dev/null || echo "-L/usr/local/lib -lmbedtls -lmbedx509 -lmbedcrypto"; \
|
||||||
fi)
|
fi)
|
||||||
EXECLDFLAGS = $(COMMONFLAGS) -lboost_program_options -lfuse
|
EXECLDFLAGS = $(COMMONFLAGS) -lboost_program_options $(FUSE_LIBS)
|
||||||
|
|
||||||
SCAN := 0
|
SCAN := 0
|
||||||
SRCDIR := .
|
SRCDIR := .
|
||||||
|
|
@ -42,14 +67,14 @@ LIBOUT := libpcloudcc_lib.so
|
||||||
|
|
||||||
# Build type specific flags
|
# Build type specific flags
|
||||||
ifeq ($(BUILD), debug)
|
ifeq ($(BUILD), debug)
|
||||||
CFLAGS += -g -O0 -DDEBUG -Wall -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26 -D_GNU_SOURCE -DPSYNC_SSL_DEBUG_LEVEL=$(SSLDBGLVL)
|
CFLAGS += -g -O0 -DDEBUG -Wall -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=$(FUSE_USE_VERSION) -D_GNU_SOURCE -DPSYNC_SSL_DEBUG_LEVEL=$(SSLDBGLVL)
|
||||||
CXXFLAGS += -g -O0 -DDEBUG -Wall -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26 -D_GNU_SOURCE -DPSYNC_SSL_DEBUG_LEVEL=$(SSLDBGLVL)
|
CXXFLAGS += -g -O0 -DDEBUG -Wall -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=$(FUSE_USE_VERSION) -D_GNU_SOURCE -DPSYNC_SSL_DEBUG_LEVEL=$(SSLDBGLVL)
|
||||||
DEBUGSRC := $(wildcard $(LIBDIR)/debug/*.c)
|
DEBUGSRC := $(wildcard $(LIBDIR)/debug/*.c)
|
||||||
DEBUGOBJ := $(notdir $(DEBUGSRC:%.c=%.o))
|
DEBUGOBJ := $(notdir $(DEBUGSRC:%.c=%.o))
|
||||||
COBJ += $(DEBUGOBJ)
|
COBJ += $(DEBUGOBJ)
|
||||||
else ifeq ($(BUILD), release)
|
else ifeq ($(BUILD), release)
|
||||||
CFLAGS += -g -O0 -DNDEBUG -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26 -D_GNU_SOURCE -DPSYNC_SSL_DEBUG_LEVEL=$(SSLDBGLVL)
|
CFLAGS += -O2 -DNDEBUG -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=$(FUSE_USE_VERSION) -D_GNU_SOURCE -DPSYNC_SSL_DEBUG_LEVEL=$(SSLDBGLVL)
|
||||||
CXXFLAGS += -g -O0 -DNDEBUG -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26 -D_GNU_SOURCE -DPSYNC_SSL_DEBUG_LEVEL=$(SSLDBGLVL)
|
CXXFLAGS += -O2 -DNDEBUG -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=$(FUSE_USE_VERSION) -D_GNU_SOURCE -DPSYNC_SSL_DEBUG_LEVEL=$(SSLDBGLVL)
|
||||||
COMMONFLAGS := $(filter-out -fsanitize=address,$(COMMONFLAGS))
|
COMMONFLAGS := $(filter-out -fsanitize=address,$(COMMONFLAGS))
|
||||||
LIBLDFLAGS := $(filter-out -fsanitize=address,$(LIBLDFLAGS))
|
LIBLDFLAGS := $(filter-out -fsanitize=address,$(LIBLDFLAGS))
|
||||||
EXECLDFLAGS := $(filter-out -fsanitize=address,$(EXECLDFLAGS))
|
EXECLDFLAGS := $(filter-out -fsanitize=address,$(EXECLDFLAGS))
|
||||||
|
|
|
||||||
13
README.md
13
README.md
|
|
@ -8,6 +8,19 @@ The target operating system and platform for this program is `linux/amd64`, and
|
||||||
|
|
||||||
I aim to support as many distributions as possible. I maintain a package for [AUR](https://aur.archlinux.org/packages/pcloudcc-lneely) and [Nix](https://github.com/lneely/nixpkgs). I do not plan on providing or maintaining any other packages, but encourage anyone interested in doing so for their own distributions.
|
I aim to support as many distributions as possible. I maintain a package for [AUR](https://aur.archlinux.org/packages/pcloudcc-lneely) and [Nix](https://github.com/lneely/nixpkgs). I do not plan on providing or maintaining any other packages, but encourage anyone interested in doing so for their own distributions.
|
||||||
|
|
||||||
|
# Compatibility Matrix
|
||||||
|
|
||||||
|
| Distribution | FUSE |
|
||||||
|
|---|---|
|
||||||
|
| Debian trixie | 2.x |
|
||||||
|
| Debian trixie | 3.x |
|
||||||
|
| Arch Linux (rolling) | 3.x latest |
|
||||||
|
| Fedora 41 | 3.x |
|
||||||
|
| Fedora (latest) | 3.x latest |
|
||||||
|
| Debian forky | 3.18+ |
|
||||||
|
|
||||||
|
All configurations require **mbedTLS 3.x**. Runtime mount testing was performed manually on FUSE 2 (libfuse 2.9.x), FUSE 3 (libfuse3 3.10.5), and FUSE 3.18+ (Debian forky container).
|
||||||
|
|
||||||
# Notices
|
# Notices
|
||||||
|
|
||||||
## Security Notice
|
## Security Notice
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Detect FUSE version and set appropriate flags
|
||||||
|
|
||||||
|
# Check if pkg-config is available
|
||||||
|
if command -v pkg-config >/dev/null 2>&1; then
|
||||||
|
# Use pkg-config if available
|
||||||
|
if pkg-config --exists fuse3 2>/dev/null; then
|
||||||
|
echo "FUSE3"
|
||||||
|
exit 0
|
||||||
|
elif pkg-config --exists fuse 2>/dev/null; then
|
||||||
|
echo "FUSE2"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fallback: search for header files in common locations
|
||||||
|
SEARCH_PATHS="/usr/include /usr/local/include /opt/local/include /opt/include"
|
||||||
|
|
||||||
|
for base in $SEARCH_PATHS; do
|
||||||
|
if [ -f "$base/fuse3/fuse.h" ]; then
|
||||||
|
echo "FUSE3"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
for base in $SEARCH_PATHS; do
|
||||||
|
if [ -f "$base/fuse/fuse.h" ]; then
|
||||||
|
echo "FUSE2"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Last resort: try to compile a test program
|
||||||
|
if command -v gcc >/dev/null 2>&1; then
|
||||||
|
# Try FUSE 3
|
||||||
|
if echo '#include <fuse.h>' | gcc -E -DFUSE_USE_VERSION=30 - >/dev/null 2>&1; then
|
||||||
|
echo "FUSE3"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
# Try FUSE 2
|
||||||
|
if echo '#include <fuse.h>' | gcc -E -DFUSE_USE_VERSION=26 - >/dev/null 2>&1; then
|
||||||
|
echo "FUSE2"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "NONE"
|
||||||
|
exit 1
|
||||||
161
pclsync/pfs.c
161
pclsync/pfs.c
|
|
@ -92,8 +92,10 @@ typedef off_t fuse_off_t;
|
||||||
|
|
||||||
static int shutdown_in_progress = 0;
|
static int shutdown_in_progress = 0;
|
||||||
volatile sig_atomic_t shutdown_requested = 0;
|
volatile sig_atomic_t shutdown_requested = 0;
|
||||||
static struct fuse_chan *psync_fuse_channel = NULL;
|
|
||||||
static struct fuse *psync_fuse = NULL;
|
static struct fuse *psync_fuse = NULL;
|
||||||
|
#if FUSE_USE_VERSION < 30
|
||||||
|
static struct fuse_chan *psync_fuse_channel = NULL;
|
||||||
|
#endif
|
||||||
static char *psync_current_mountpoint = NULL;
|
static char *psync_current_mountpoint = NULL;
|
||||||
static psync_generic_callback_t psync_start_callback = NULL;
|
static psync_generic_callback_t psync_start_callback = NULL;
|
||||||
char *pfs_fake_prefix = NULL;
|
char *pfs_fake_prefix = NULL;
|
||||||
|
|
@ -786,7 +788,11 @@ static int pfs_getrootattr(struct FUSE_STAT *stbuf) {
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#if FUSE_USE_VERSION >= 30
|
||||||
|
static int pfs_getattr(const char *path, struct FUSE_STAT *stbuf, struct fuse_file_info *fi) {
|
||||||
|
#else
|
||||||
static int pfs_getattr(const char *path, struct FUSE_STAT *stbuf) {
|
static int pfs_getattr(const char *path, struct FUSE_STAT *stbuf) {
|
||||||
|
#endif
|
||||||
psync_sql_res *res;
|
psync_sql_res *res;
|
||||||
psync_variant_row row;
|
psync_variant_row row;
|
||||||
psync_fspath_t *fpath;
|
psync_fspath_t *fpath;
|
||||||
|
|
@ -877,15 +883,29 @@ static int filler_decoded(pcrypto_textdec_t dec,
|
||||||
namedec = pcryptofolder_flddecode_filename(dec, name);
|
namedec = pcryptofolder_flddecode_filename(dec, name);
|
||||||
if (!namedec)
|
if (!namedec)
|
||||||
return 0;
|
return 0;
|
||||||
|
#if FUSE_USE_VERSION >= 30
|
||||||
|
ret = filler(buf, namedec, st, off, FUSE_FILL_DIR_PLUS);
|
||||||
|
#else
|
||||||
ret = filler(buf, namedec, st, off);
|
ret = filler(buf, namedec, st, off);
|
||||||
|
#endif
|
||||||
pmem_free(PMEM_SUBSYS_OTHER, namedec);
|
pmem_free(PMEM_SUBSYS_OTHER, namedec);
|
||||||
return ret;
|
return ret;
|
||||||
} else
|
} else
|
||||||
|
#if FUSE_USE_VERSION >= 30
|
||||||
|
return filler(buf, name, st, off, FUSE_FILL_DIR_PLUS);
|
||||||
|
#else
|
||||||
return filler(buf, name, st, off);
|
return filler(buf, name, st, off);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FUSE_USE_VERSION >= 30
|
||||||
|
static int pfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
||||||
|
fuse_off_t offset, struct fuse_file_info *fi,
|
||||||
|
enum fuse_readdir_flags readdir_flags) {
|
||||||
|
#else
|
||||||
static int pfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
static int pfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
||||||
fuse_off_t offset, struct fuse_file_info *fi) {
|
fuse_off_t offset, struct fuse_file_info *fi) {
|
||||||
|
#endif
|
||||||
psync_sql_res *res;
|
psync_sql_res *res;
|
||||||
psync_variant_row row;
|
psync_variant_row row;
|
||||||
psync_fsfolderid_t folderid;
|
psync_fsfolderid_t folderid;
|
||||||
|
|
@ -918,9 +938,15 @@ static int pfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
dec = NULL;
|
dec = NULL;
|
||||||
|
#if FUSE_USE_VERSION >= 30
|
||||||
|
filler(buf, ".", NULL, 0, FUSE_FILL_DIR_PLUS);
|
||||||
|
if (folderid != 0)
|
||||||
|
filler(buf, "..", NULL, 0, FUSE_FILL_DIR_PLUS);
|
||||||
|
#else
|
||||||
filler(buf, ".", NULL, 0);
|
filler(buf, ".", NULL, 0);
|
||||||
if (folderid != 0)
|
if (folderid != 0)
|
||||||
filler(buf, "..", NULL, 0);
|
filler(buf, "..", NULL, 0);
|
||||||
|
#endif
|
||||||
folder = pfs_task_get_folder_tasks_rdlocked(folderid);
|
folder = pfs_task_get_folder_tasks_rdlocked(folderid);
|
||||||
if (folderid >= 0) {
|
if (folderid >= 0) {
|
||||||
res = psql_query_nolock(
|
res = psql_query_nolock(
|
||||||
|
|
@ -1689,6 +1715,7 @@ static int pfs_creat(const char *path, mode_t mode,
|
||||||
encoder);
|
encoder);
|
||||||
pfs_task_release_folder_tasks_locked(folder);
|
pfs_task_release_folder_tasks_locked(folder);
|
||||||
psql_unlock();
|
psql_unlock();
|
||||||
|
of->canmodify = (fpath->permissions & PSYNC_PERM_MODIFY) != 0;
|
||||||
of->newfile = 1;
|
of->newfile = 1;
|
||||||
of->modified = 1;
|
of->modified = 1;
|
||||||
ret = open_write_files(of, 1);
|
ret = open_write_files(of, 1);
|
||||||
|
|
@ -2885,7 +2912,11 @@ static int pfs_is_nonempty_folder(psync_fsfolderid_t parent_folderid,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FUSE_USE_VERSION >= 30
|
||||||
|
static int pfs_rename(const char *old_path, const char *new_path, unsigned int rename_flags) {
|
||||||
|
#else
|
||||||
static int pfs_rename(const char *old_path, const char *new_path) {
|
static int pfs_rename(const char *old_path, const char *new_path) {
|
||||||
|
#endif
|
||||||
psync_fspath_t *fold_path, *fnew_path;
|
psync_fspath_t *fold_path, *fnew_path;
|
||||||
psync_sql_res *res;
|
psync_sql_res *res;
|
||||||
psync_fstask_folder_t *folder;
|
psync_fstask_folder_t *folder;
|
||||||
|
|
@ -3057,13 +3088,21 @@ static int pfs_statfs(const char *path, struct statvfs *stbuf) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FUSE_USE_VERSION >= 30
|
||||||
|
static int pfs_chmod(const char *path, mode_t mode, struct fuse_file_info *fi) {
|
||||||
|
#else
|
||||||
static int pfs_chmod(const char *path, mode_t mode) {
|
static int pfs_chmod(const char *path, mode_t mode) {
|
||||||
|
#endif
|
||||||
pfs_set_thread_name();
|
pfs_set_thread_name();
|
||||||
pdbg_logf(D_NOTICE, "chmod %s %u", path, (unsigned)mode);
|
pdbg_logf(D_NOTICE, "chmod %s %u", path, (unsigned)mode);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FUSE_USE_VERSION >= 30
|
||||||
|
static int pfs_chown(const char *path, uid_t uid, gid_t gid, struct fuse_file_info *fi) {
|
||||||
|
#else
|
||||||
static int pfs_chown(const char *path, uid_t uid, gid_t gid) {
|
static int pfs_chown(const char *path, uid_t uid, gid_t gid) {
|
||||||
|
#endif
|
||||||
pfs_set_thread_name();
|
pfs_set_thread_name();
|
||||||
pdbg_logf(D_NOTICE, "chown %s %u %u", path, (unsigned)uid, (unsigned)gid);
|
pdbg_logf(D_NOTICE, "chown %s %u %u", path, (unsigned)uid, (unsigned)gid);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -3229,7 +3268,11 @@ static int pfs_setcrtime(const char *path, const struct timespec *tv) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if FUSE_USE_VERSION >= 30
|
||||||
|
static int pfs_utimens(const char *path, const struct timespec tv[2], struct fuse_file_info *fi) {
|
||||||
|
#else
|
||||||
static int pfs_utimens(const char *path, const struct timespec tv[2]) {
|
static int pfs_utimens(const char *path, const struct timespec tv[2]) {
|
||||||
|
#endif
|
||||||
pfs_set_thread_name();
|
pfs_set_thread_name();
|
||||||
pdbg_logf(D_NOTICE, "utimens %s %lu", path, tv[1].tv_sec);
|
pdbg_logf(D_NOTICE, "utimens %s %lu", path, tv[1].tv_sec);
|
||||||
return pfs_set_time(path, &tv[1], 0);
|
return pfs_set_time(path, &tv[1], 0);
|
||||||
|
|
@ -3286,6 +3329,27 @@ static int pfs_ftruncate(const char *path, fuse_off_t size,
|
||||||
(unsigned long)size);
|
(unsigned long)size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FUSE_USE_VERSION >= 30
|
||||||
|
static int pfs_truncate(const char *path, fuse_off_t size, struct fuse_file_info *fi) {
|
||||||
|
struct fuse_file_info fi_local;
|
||||||
|
int ret;
|
||||||
|
pfs_set_thread_name();
|
||||||
|
pdbg_logf(D_NOTICE, "truncate %s %lu", path, (unsigned long)size);
|
||||||
|
|
||||||
|
if (fi) {
|
||||||
|
return pfs_ftruncate(path, size, fi);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&fi_local, 0, sizeof(fi_local));
|
||||||
|
ret = pfs_open(path, &fi_local);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
ret = pfs_ftruncate(path, size, &fi_local);
|
||||||
|
pfs_flush(path, &fi_local);
|
||||||
|
pfs_release(path, &fi_local);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#else
|
||||||
static int pfs_truncate(const char *path, fuse_off_t size) {
|
static int pfs_truncate(const char *path, fuse_off_t size) {
|
||||||
struct fuse_file_info fi;
|
struct fuse_file_info fi;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
@ -3300,6 +3364,7 @@ static int pfs_truncate(const char *path, fuse_off_t size) {
|
||||||
pfs_release(path, &fi);
|
pfs_release(path, &fi);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void pfs_start_callback_timer(psync_timer_t timer, void *ptr) {
|
static void pfs_start_callback_timer(psync_timer_t timer, void *ptr) {
|
||||||
psync_generic_callback_t callback;
|
psync_generic_callback_t callback;
|
||||||
|
|
@ -3309,7 +3374,11 @@ static void pfs_start_callback_timer(psync_timer_t timer, void *ptr) {
|
||||||
prun_thread("fs start callback", callback);
|
prun_thread("fs start callback", callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if FUSE_USE_VERSION >= 30
|
||||||
|
static void *pfs_init(struct fuse_conn_info *conn, struct fuse_config *cfg) {
|
||||||
|
#else
|
||||||
static void *pfs_init(struct fuse_conn_info *conn) {
|
static void *pfs_init(struct fuse_conn_info *conn) {
|
||||||
|
#endif
|
||||||
#if defined(FUSE_CAP_ASYNC_READ)
|
#if defined(FUSE_CAP_ASYNC_READ)
|
||||||
conn->want |= FUSE_CAP_ASYNC_READ;
|
conn->want |= FUSE_CAP_ASYNC_READ;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -3546,8 +3615,12 @@ static void pfs_do_stop(void) {
|
||||||
mp = psync_fuse_get_mountpoint();
|
mp = psync_fuse_get_mountpoint();
|
||||||
if (mp) {
|
if (mp) {
|
||||||
if (stat(mp, &st_before) == 0) {
|
if (stat(mp, &st_before) == 0) {
|
||||||
|
#if FUSE_USE_VERSION >= 30
|
||||||
|
fuse_unmount(psync_fuse);
|
||||||
|
#else
|
||||||
fuse_unmount(mp, psync_fuse_channel);
|
fuse_unmount(mp, psync_fuse_channel);
|
||||||
psync_fuse_channel = NULL;
|
psync_fuse_channel = NULL;
|
||||||
|
#endif
|
||||||
clock_gettime(CLOCK_REALTIME, &ts);
|
clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
|
|
||||||
// Check if the mountpoint is still accessible
|
// Check if the mountpoint is still accessible
|
||||||
|
|
@ -3633,13 +3706,16 @@ static void psync_fuse_thread() {
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&start_mutex);
|
pthread_mutex_unlock(&start_mutex);
|
||||||
pdbg_logf(D_NOTICE, "running fuse_loop_mt");
|
pdbg_logf(D_NOTICE, "running fuse_loop_mt");
|
||||||
|
#if FUSE_USE_VERSION >= 32
|
||||||
|
struct fuse_loop_config loop_config;
|
||||||
|
loop_config.clone_fd = 1;
|
||||||
|
loop_config.max_idle_threads = 10;
|
||||||
|
fr = fuse_loop_mt(psync_fuse, &loop_config);
|
||||||
|
#elif FUSE_USE_VERSION >= 30
|
||||||
|
fr = fuse_loop_mt_31(psync_fuse, 1);
|
||||||
|
#else
|
||||||
fr = fuse_loop_mt(psync_fuse);
|
fr = fuse_loop_mt(psync_fuse);
|
||||||
|
#endif
|
||||||
if (shutdown_requested) {
|
|
||||||
pdbg_logf(D_NOTICE, "shutdown requested, exiting fuse loop");
|
|
||||||
pfs_do_stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
pdbg_logf(D_NOTICE, "fuse_loop_mt exited with code %d, running fuse_destroy", fr);
|
pdbg_logf(D_NOTICE, "fuse_loop_mt exited with code %d, running fuse_destroy", fr);
|
||||||
pthread_mutex_lock(&start_mutex);
|
pthread_mutex_lock(&start_mutex);
|
||||||
fuse_destroy(psync_fuse);
|
fuse_destroy(psync_fuse);
|
||||||
|
|
@ -3650,28 +3726,6 @@ static void psync_fuse_thread() {
|
||||||
pthread_mutex_unlock(&start_mutex);
|
pthread_mutex_unlock(&start_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if FUSE 3 is installed on the user's machine.
|
|
||||||
// Returns false if FUSE version is less than 3.
|
|
||||||
static char is_fuse3_installed_on_system() {
|
|
||||||
// Assuming that fusermount3 is only available on FUSE 3.
|
|
||||||
FILE *pipe = popen("which fusermount3", "r");
|
|
||||||
|
|
||||||
if (!pipe) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char output[1024];
|
|
||||||
memset(output, 0, sizeof(output));
|
|
||||||
|
|
||||||
if (fgets(output, sizeof(output), pipe) != NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pclose(pipe);
|
|
||||||
size_t outlen = strlen(output);
|
|
||||||
|
|
||||||
return outlen > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pfs_do_start() {
|
static int pfs_do_start() {
|
||||||
char *mp;
|
char *mp;
|
||||||
|
|
@ -3684,10 +3738,6 @@ static int pfs_do_start() {
|
||||||
fuse_opt_add_arg(&args, "argv");
|
fuse_opt_add_arg(&args, "argv");
|
||||||
fuse_opt_add_arg(&args, "-oauto_unmount");
|
fuse_opt_add_arg(&args, "-oauto_unmount");
|
||||||
fuse_opt_add_arg(&args, "-ofsname=" DEFAULT_FUSE_MOUNT_POINT ".fs");
|
fuse_opt_add_arg(&args, "-ofsname=" DEFAULT_FUSE_MOUNT_POINT ".fs");
|
||||||
if (!is_fuse3_installed_on_system()) {
|
|
||||||
fuse_opt_add_arg(&args, "-ononempty");
|
|
||||||
}
|
|
||||||
fuse_opt_add_arg(&args, "-ohard_remove");
|
|
||||||
|
|
||||||
// Add user-specified FUSE options from environment variable
|
// Add user-specified FUSE options from environment variable
|
||||||
const char *fuse_opts_env = getenv("PCLOUD_FUSE_OPTS");
|
const char *fuse_opts_env = getenv("PCLOUD_FUSE_OPTS");
|
||||||
|
|
@ -3739,8 +3789,12 @@ static int pfs_do_start() {
|
||||||
psync_oper.chmod = pfs_chmod;
|
psync_oper.chmod = pfs_chmod;
|
||||||
psync_oper.chown = pfs_chown;
|
psync_oper.chown = pfs_chown;
|
||||||
psync_oper.utimens = pfs_utimens;
|
psync_oper.utimens = pfs_utimens;
|
||||||
|
#if FUSE_USE_VERSION >= 30
|
||||||
|
psync_oper.truncate = pfs_truncate;
|
||||||
|
#else
|
||||||
psync_oper.ftruncate = pfs_ftruncate;
|
psync_oper.ftruncate = pfs_ftruncate;
|
||||||
psync_oper.truncate = pfs_truncate;
|
psync_oper.truncate = pfs_truncate;
|
||||||
|
#endif
|
||||||
|
|
||||||
psync_oper.setxattr = pfs_xatr_set;
|
psync_oper.setxattr = pfs_xatr_set;
|
||||||
psync_oper.getxattr = pfs_xatr_get;
|
psync_oper.getxattr = pfs_xatr_get;
|
||||||
|
|
@ -3770,18 +3824,45 @@ static int pfs_do_start() {
|
||||||
goto err00;
|
goto err00;
|
||||||
}
|
}
|
||||||
|
|
||||||
psync_fuse_channel = fuse_mount(mp, &args);
|
#if FUSE_USE_VERSION >= 30
|
||||||
if (pdbg_unlikely(!psync_fuse_channel)) {
|
psync_fuse = fuse_new(&args, &psync_oper, sizeof(psync_oper), NULL);
|
||||||
|
if (pdbg_unlikely(!psync_fuse)) {
|
||||||
|
pdbg_logf(D_CRITICAL,
|
||||||
|
"CRITICAL ERROR: fuse_new() failed. "
|
||||||
|
"The FUSE filesystem cannot be started. errno=%d (%s)",
|
||||||
|
errno, strerror(errno));
|
||||||
|
goto err0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fuse_mount(psync_fuse, mp) != 0) {
|
||||||
|
pdbg_logf(D_CRITICAL,
|
||||||
|
"CRITICAL ERROR: fuse_mount() failed for mount point %s. "
|
||||||
|
"The FUSE filesystem cannot be started. errno=%d (%s)",
|
||||||
|
mp, errno, strerror(errno));
|
||||||
|
goto err1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
struct fuse_chan *ch = fuse_mount(mp, &args);
|
||||||
|
if (pdbg_unlikely(!ch)) {
|
||||||
pdbg_logf(D_CRITICAL,
|
pdbg_logf(D_CRITICAL,
|
||||||
"CRITICAL ERROR: fuse_mount() failed for mount point %s. "
|
"CRITICAL ERROR: fuse_mount() failed for mount point %s. "
|
||||||
"The FUSE filesystem cannot be started. errno=%d (%s)",
|
"The FUSE filesystem cannot be started. errno=%d (%s)",
|
||||||
mp, errno, strerror(errno));
|
mp, errno, strerror(errno));
|
||||||
goto err0;
|
goto err0;
|
||||||
}
|
}
|
||||||
psync_fuse = fuse_new(psync_fuse_channel, &args, &psync_oper,
|
|
||||||
sizeof(psync_oper), NULL);
|
psync_fuse = fuse_new(ch, &args, &psync_oper, sizeof(psync_oper), NULL);
|
||||||
if (pdbg_unlikely(!psync_fuse))
|
if (pdbg_unlikely(!psync_fuse)) {
|
||||||
goto err1;
|
pdbg_logf(D_CRITICAL,
|
||||||
|
"CRITICAL ERROR: fuse_new() failed. "
|
||||||
|
"The FUSE filesystem cannot be started. errno=%d (%s)",
|
||||||
|
errno, strerror(errno));
|
||||||
|
fuse_unmount(mp, ch);
|
||||||
|
goto err0;
|
||||||
|
}
|
||||||
|
psync_fuse_channel = ch;
|
||||||
|
#endif
|
||||||
|
|
||||||
psync_current_mountpoint = mp;
|
psync_current_mountpoint = mp;
|
||||||
started = 1;
|
started = 1;
|
||||||
pthread_mutex_unlock(&start_mutex);
|
pthread_mutex_unlock(&start_mutex);
|
||||||
|
|
@ -3789,7 +3870,7 @@ static int pfs_do_start() {
|
||||||
prun_thread("fuse", psync_fuse_thread);
|
prun_thread("fuse", psync_fuse_thread);
|
||||||
return 0;
|
return 0;
|
||||||
err1:
|
err1:
|
||||||
fuse_unmount(mp, psync_fuse_channel);
|
fuse_destroy(psync_fuse);
|
||||||
err0:
|
err0:
|
||||||
pmem_free(PMEM_SUBSYS_OTHER, mp);
|
pmem_free(PMEM_SUBSYS_OTHER, mp);
|
||||||
err00:
|
err00:
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,6 @@
|
||||||
DAMAGE.
|
DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define FUSE_USE_VERSION 26
|
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fuse.h>
|
#include <fuse.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue