Browse Source

Build improvements (#1501)

* Remove python dependency
* Remove ecfd
* Improve makefiles
* Make preload.so more 32bit compatible
pull/1502/head
trapexit 2 months ago
committed by GitHub
parent
commit
b18aba86b6
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 6
      .gitignore
  2. 269
      Makefile
  3. 2
      buildtools/build-release
  4. 9
      buildtools/containerfiles/debian.10.arm64
  5. 2
      buildtools/containerfiles/fedora.43.amd64
  6. 2
      buildtools/containerfiles/fedora.43.arm64
  7. 2
      buildtools/containerfiles/rockylinux.10.amd64
  8. 2
      buildtools/containerfiles/rockylinux.10.arm64
  9. 2
      buildtools/containerfiles/rockylinux.10.riscv64
  10. 2
      buildtools/containerfiles/rockylinux.8.amd64
  11. 2
      buildtools/containerfiles/rockylinux.8.arm64
  12. 2
      buildtools/containerfiles/rockylinux.8.armhf
  13. 2
      buildtools/containerfiles/rockylinux.8.i386
  14. 2
      buildtools/containerfiles/rockylinux.9.amd64
  15. 2
      buildtools/containerfiles/rockylinux.9.arm64
  16. 2
      buildtools/containerfiles/rockylinux.9.armhf
  17. 2
      buildtools/containerfiles/rockylinux.9.i386
  18. 13
      buildtools/containerfiles/static.riscv64
  19. 282
      buildtools/git2debcl
  20. 23
      buildtools/install-build-pkgs
  21. 19
      buildtools/install-build-tools
  22. 4
      buildtools/update-version
  23. 10
      debian/rules
  24. 139
      libfuse/Makefile
  25. 17
      libfuse/ecfd/LICENSE
  26. 16
      libfuse/ecfd/README.md
  27. 32
      libfuse/ecfd/build
  28. 10
      libfuse/ecfd/tests/HAVE_FORK.c
  29. 7
      libfuse/ecfd/tests/HAVE_MALLOC_TRIM.c
  30. 14
      libfuse/ecfd/tests/HAVE_STRUCT_STAT_ST_ATIM.c
  31. 11
      libfuse/ecfd/tests/HAVE_UTIMENSAT.c
  32. 4
      libfuse/ecfd/tests/static_assert.h
  33. 13
      libfuse/include/stat_utils.h
  34. 1
      libfuse/lib/buffer.c
  35. 1014
      libfuse/lib/debug.cpp
  36. 23
      libfuse/lib/fuse.cpp
  37. 1
      libfuse/lib/fuse_loop.cpp
  38. 5
      libfuse/lib/fuse_lowlevel.cpp
  39. 49
      libfuse/lib/fuse_misc.h
  40. 1
      libfuse/lib/fuse_opt.c
  41. 1
      libfuse/lib/fuse_session.c
  42. 2
      libfuse/lib/helper.c
  43. 6
      libfuse/lib/mount_generic.c
  44. 7
      libfuse/lib/pin_threads.cpp
  45. 3
      libfuse/util/fusermount.c
  46. 6
      mergerfs.spec
  47. 8
      src/error.hpp
  48. 8
      src/fuse_listxattr.cpp
  49. 2
      src/fuse_rmdir.cpp
  50. 5
      src/mergerfs_fsck.cpp
  51. 56
      tools/preload.c

6
.gitignore

@ -14,12 +14,16 @@
# build artifacts
mergerfs
obj/
build/
src/version.hpp
VERSION
# Debian files
debian/files
debian/changelog
debian/debhelper-build-stamp
debian/mergerfs.debhelper.log
debian/mergerfs.substvars
# RPM files
rpmbuild/

269
Makefile

@ -12,35 +12,39 @@
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
GIT = git
TAR = tar
MKDIR = mkdir
TOUCH = touch
CP = cp
RM = rm
LN = ln
FIND = find
INSTALL = install
MKTEMP = mktemp
STRIP ?= strip
SED = sed
GIT2DEBCL = ./buildtools/git2debcl
PKGCONFIG = pkg-config
GIT_REPO = 0
CP ?= cp
FAKEROOT ?= fakeroot
FIND ?= find
GIT ?= git
GIT2DEBCL ?= buildtools/git2debcl
INSTALL ?= install
LN ?= ln
MKDIR ?= mkdir
MKTEMP ?= mktemp
MV ?= mv
RM ?= rm
SED ?= sed
STRIP ?= strip
TAR ?= tar
TOUCH ?= touch
BUILDDIR := build
ifneq ($(GIT_REPO),0)
ifneq ($(shell $(GIT) --version 2> /dev/null),)
ifeq ($(shell test -e .git; echo $$?),0)
GIT_REPO = 1
endif
endif
endif
USE_XATTR = 1
UGID_USE_RWLOCK = 0
USE_XATTR ?= 1
UGID_USE_RWLOCK ?= 0
ifeq ($(NDEBUG),1)
OPT_FLAGS := -O2 -DNDEBUG
else
OPT_FLAGS := -O0 -DDEBUG -g
OPT_FLAGS := -O0 -g -fno-omit-frame-pointer -DDEBUG
endif
ifeq ($(STATIC),1)
@ -55,66 +59,79 @@ else
LTO_FLAGS :=
endif
SRC = $(wildcard src/*.cpp)
OBJS = $(SRC:src/%.cpp=build/.src/%.o)
DEPS = $(SRC:src/%.cpp=build/.src/%.d)
SRC := $(wildcard src/*.cpp)
OBJS := $(SRC:src/%.cpp=build/.src/%.o)
DEPS := $(SRC:src/%.cpp=build/.src/%.d)
TESTS = $(wildcard tests/*.cpp)
TESTS_OBJS = $(filter-out build/.src/mergerfs.o,$(OBJS))
TESTS := $(wildcard tests/*.cpp)
TESTS_OBJS := $(filter-out build/.src/mergerfs.o,$(OBJS))
TESTS_OBJS += $(TESTS:tests/%.cpp=build/.tests/%.o)
TESTS_DEPS = $(TESTS:tests/%.cpp=build/.tests/%.d)
TESTS_DEPS := $(TESTS:tests/%.cpp=build/.tests/%.d)
TESTS_DEPS += $(DEPS)
MANPAGE = mergerfs.1
CFLAGS ?= ${OPT_FLAGS}
CFLAGS := ${CFLAGS} \
-Wall \
-Wno-unused-result
CXXFLAGS ?= ${OPT_FLAGS}
CXXFLAGS := \
${CXXFLAGS} \
-std=c++17 \
$(STATIC_FLAGS) \
$(LTO_FLAGS) \
-Isrc \
-Wall \
-Wno-unused-result \
-MMD
FUSE_FLAGS = \
-Ilibfuse/include \
-D_FILE_OFFSET_BITS=64
MFS_FLAGS = \
-DUSE_XATTR=$(USE_XATTR) \
-DUGID_USE_RWLOCK=$(UGID_USE_RWLOCK)
TESTS_FLAGS = \
-Isrc \
-DTESTS
LDFLAGS := \
${LDFLAGS} \
-pthread \
-lrt \
-lstdc++fs
MANPAGE := mergerfs.1
CPPFLAGS ?=
override CPPFLAGS += \
-D_FILE_OFFSET_BITS=64
CFLAGS ?= \
$(OPT_FLAGS) \
-Wall \
-Wno-unused-result \
-pipe
override CFLAGS += \
-MMD \
-MP
CXXFLAGS ?= \
$(OPT_FLAGS) \
$(STATIC_FLAGS) \
$(LTO_FLAGS) \
-Wall \
-Wno-unused-result \
-pipe
override CXXFLAGS += \
-std=c++17 \
-MMD \
-MP
override INC_FLAGS := \
-Isrc \
-Ilibfuse/include
override MFS_FLAGS := \
-DUSE_XATTR=$(USE_XATTR) \
-DUGID_USE_RWLOCK=$(UGID_USE_RWLOCK)
override TESTS_FLAGS := \
-Isrc \
-DTESTS
LIBFUSE := libfuse/$(BUILDDIR)/libfuse.a
LDFLAGS ?=
LDLIBS := \
-lrt \
-latomic \
-pthread \
-lstdc++fs
override LDLIBS += \
$(LIBFUSE)
# https://www.gnu.org/prep/standards/html_node/Directory-Variables.html
DESTDIR =
PREFIX = /usr/local
EXEC_PREFIX = $(PREFIX)
DATAROOTDIR = $(PREFIX)/share
DATADIR = $(DATAROOTDIR)
BINDIR = $(EXEC_PREFIX)/bin
SBINDIR = $(EXEC_PREFIX)/sbin
LIBDIR = $(EXEC_PREFIX)/lib
MANDIR = $(DATAROOTDIR)/man
MAN1DIR = $(MANDIR)/man1
INSTALLBINDIR = $(DESTDIR)$(BINDIR)
INSTALLSBINDIR = $(DESTDIR)$(SBINDIR)
INSTALLLIBDIR = $(DESTDIR)$(LIBDIR)/mergerfs
INSTALLMAN1DIR = $(DESTDIR)$(MAN1DIR)
DESTDIR ?=
PREFIX ?= /usr/local
EXEC_PREFIX ?= $(PREFIX)
DATAROOTDIR ?= $(PREFIX)/share
DATADIR ?= $(DATAROOTDIR)
BINDIR ?= $(EXEC_PREFIX)/bin
SBINDIR ?= $(EXEC_PREFIX)/sbin
LIBDIR ?= $(EXEC_PREFIX)/lib
MANDIR ?= $(DATAROOTDIR)/man
MAN1DIR ?= $(MANDIR)/man1
INSTALLBINDIR ?= $(DESTDIR)$(BINDIR)
INSTALLSBINDIR ?= $(DESTDIR)$(SBINDIR)
INSTALLLIBDIR ?= $(DESTDIR)$(LIBDIR)/mergerfs
INSTALLMAN1DIR ?= $(DESTDIR)$(MAN1DIR)
.PHONY: all
all: mergerfs
all: libfuse $(BUILDDIR)/mergerfs $(BUILDDIR)/fsck.mergerfs $(BUILDDIR)/mergerfs.collect-info
.PHONY: help
help:
@ -123,23 +140,25 @@ help:
@echo "make STATIC=1 - build static binary"
@echo "make LTO=1 - build with link time optimization"
objects: version build/stamp
$(MAKE) $(OBJS)
tests-objects:
$(MAKE) $(TESTS_OBJS)
$(BUILDDIR)/mergerfs: $(LIBFUSE) src/version.hpp $(OBJS)
$(CXX) $(CXXFLAGS) $(INC_FLAGS) $(MFS_FLAGS) $(CPPFLAGS) $(OBJS) -o $@ $(LDFLAGS) $(LDLIBS)
$(BUILDDIR)/fsck.mergerfs:
$(LN) -sf "mergerfs" $@
build/mergerfs: libfuse objects
$(CXX) $(CXXFLAGS) $(FUSE_FLAGS) $(MFS_FLAGS) $(CPPFLAGS) $(OBJS) -o $@ libfuse/build/libfuse.a $(LDFLAGS)
$(BUILDDIR)/mergerfs.collect-info:
$(LN) -sf "mergerfs" $@
build/tests: build/mergerfs tests-objects
$(CXX) $(CXXFLAGS) $(TESTS_FLAGS) $(FUSE_FLAGS) $(MFS_FLAGS) $(CPPFLAGS) $(TESTS_OBJS) -o $@ libfuse/build/libfuse.a $(LDFLAGS)
$(BUILDDIR)/tests: $(BUILDDIR)/mergerfs $(TESTS_OBJS)
$(CXX) $(CXXFLAGS) $(TESTS_FLAGS) $(INC_FLAGS) $(MFS_FLAGS) $(CPPFLAGS) $(TESTS_OBJS) -o $@ $(LDFLAGS) $(LDLIBS)
mergerfs: build/mergerfs
ln -fs "mergerfs" "build/fsck.mergerfs"
ln -fs "mergerfs" "build/mergerfs.collect-info"
.PHONY: libfuse
$(LIBFUSE):
libfuse:
$(MAKE) NDEBUG=$(NDEBUG) -C libfuse
tests: build/tests
tests: $(BUILDDIR)/tests
changelog:
ifeq ($(GIT_REPO),1)
@ -149,27 +168,29 @@ else
endif
.PHONY: version
version:
version: src/version.hpp
src/version.hpp:
./buildtools/update-version
build/stamp:
$(MKDIR) -p build/.src build/.tests
$(BUILDDIR)/stamp:
$(MKDIR) -p $(BUILDDIR)/.src $(BUILDDIR)/.tests
$(TOUCH) $@
build/.src/%.o: src/%.cpp
$(CXX) $(CXXFLAGS) $(FUSE_FLAGS) $(MFS_FLAGS) $(CPPFLAGS) -c $< -o $@
$(BUILDDIR)/.src/%.o: src/%.cpp $(BUILDDIR)/stamp
$(CXX) $(CXXFLAGS) $(INC_FLAGS) $(MFS_FLAGS) $(CPPFLAGS) -c $< -o $@
build/.tests/%.o: tests/%.cpp
$(CXX) $(CXXFLAGS) $(TESTS_FLAGS) $(FUSE_FLAGS) $(MFS_FLAGS) $(CPPFLAGS) -c $< -o $@
$(BUILDDIR)/.tests/%.o: tests/%.cpp
$(CXX) $(CXXFLAGS) $(TESTS_FLAGS) $(INC_FLAGS) $(MFS_FLAGS) $(CPPFLAGS) -c $< -o $@
build/preload.so: build/stamp tools/preload.c
$(CC) -shared -fPIC $(CFLAGS) $(CPPFLAGS) -o $@ tools/preload.c
$(BUILDDIR)/preload.so: $(BUILDDIR)/stamp tools/preload.c
$(CC) -shared -fPIC $(CFLAGS) -o $@ tools/preload.c
preload: build/preload.so
preload: $(BUILDDIR)/preload.so
.PHONY: clean
clean: rpm-clean
$(RM) -rf build
$(RM) -rf $(BUILDDIR)
$(FIND) . -name "*~" -delete
$(MAKE) -C libfuse clean
@ -181,24 +202,29 @@ endif
.PHONY: install
install: install-base install-mount-tools install-preload install-man
install-base: build/mergerfs
.PHONY: install-base
install-base: all
$(MKDIR) -p "$(INSTALLBINDIR)"
$(INSTALL) -v -m 0755 "build/mergerfs" "$(INSTALLBINDIR)/mergerfs"
ln -s "mergerfs" "${INSTALLBINDIR}/fsck.mergerfs"
ln -s "mergerfs" "${INSTALLBINDIR}/mergerfs.collect-info"
$(INSTALL) -v -m 0755 "$(BUILDDIR)/mergerfs" "$(INSTALLBINDIR)/mergerfs"
$(LN) -fs "mergerfs" "${INSTALLBINDIR}/fsck.mergerfs"
$(LN) -fs "mergerfs" "${INSTALLBINDIR}/mergerfs.collect-info"
.PHONY: install-mount-tools
install-mount-tools: install-base
$(MKDIR) -p "$(INSTALLBINDIR)"
$(MAKE) -C libfuse install
.PHONY: install-man
install-man: man/$(MANPAGE)
$(MKDIR) -p "$(INSTALLMAN1DIR)"
$(INSTALL) -v -m 0644 "man/$(MANPAGE)" "$(INSTALLMAN1DIR)/$(MANPAGE)"
.PHONY: install-preload
install-preload: preload
$(MKDIR) -p "$(INSTALLLIBDIR)"
$(INSTALL) -v -m 444 "build/preload.so" "$(INSTALLLIBDIR)/preload.so"
$(INSTALL) -v -m 444 "$(BUILDDIR)/preload.so" "$(INSTALLLIBDIR)/preload.so"
.PHONY: install-strip
install-strip: install-base
$(STRIP) "$(INSTALLBINDIR)/mergerfs"
@ -225,29 +251,34 @@ tarball: changelog version
$(TAR) --exclude=.git -cz -C $(TMPDIR) -f $(FILENAME).tar.gz $(FILENAME)
$(RM) -rf $(TMPDIR)
.PHONY: debian-changelog
debian-changelog:
ifeq ($(GIT_REPO),1)
$(GIT2DEBCL) --name mergerfs > debian/changelog
else
cp ChangeLog debian/changelog
$(CP) -v ChangeLog debian/changelog
endif
.PHONY: signed-deb
signed-deb:
$(MAKE) distclean
$(MAKE) debian-changelog
fakeroot dpkg-buildpackage -nc
$(FAKEROOT) dpkg-buildpackage -nc
.PHONY: deb
deb:
$(MAKE) distclean
$(MAKE) debian-changelog
fakeroot dpkg-buildpackage -nc -uc -us
mkdir -p ./build/pkgs/
mv -v ../mergerfs*deb ./build/pkgs/
$(MAKE) version
$(FAKEROOT) dpkg-buildpackage -nc -uc -us
$(MKDIR) -p ./$(BUILDDIR)/pkgs/
$(MV) -v ../mergerfs*deb ./$(BUILDDIR)/pkgs/
.PHONY: rpm-clean
rpm-clean:
$(RM) -rf rpmbuild
.PHONY: rpm
rpm: tarball
$(eval VERSION := $(shell cat VERSION))
$(eval VERSION := $(subst -,_,$(VERSION)))
@ -262,37 +293,55 @@ rpm: tarball
install-build-pkgs:
./buildtools/install-build-pkgs
.PHONY: libfuse
libfuse:
$(MAKE) NDEBUG=$(NDEBUG) -C libfuse
.PHONY: release release-amd64
.PHONY: release
release:
./buildtools/build-release \
--target=all \
--cleanup \
--branch=$(shell git branch --show-current)
.PHONY: release-sample
release-sample:
./buildtools/build-release \
--target=debian.12.amd64 \
--cleanup \
--branch=$(shell git branch --show-current)
.PHONY: release-amd64
release-amd64:
./buildtools/build-release \
--target=amd64 \
--cleanup \
--branch=$(shell git branch --show-current)
.PHONY: release-arm64
release-arm64:
./buildtools/build-release \
--target=arm64 \
--cleanup \
--branch=$(shell git branch --show-current)
.PHONY: release-riscv64
release-riscv64:
./buildtools/build-release \
--target=riscv64 \
--cleanup \
--branch=$(shell git branch --show-current)
.PHONY: release-armhf
release-armhf:
./buildtools/build-release \
--target=armhf \
--cleanup \
--branch=$(shell git branch --show-current)
.PHONY: release-static
release-static:
./buildtools/build-release \
--target=static \
--cleanup \
--branch=$(shell git branch --show-current)
.PHONY: tags
tags:
rm -fv TAGS
find . -name "*.c" -print | etags --append -

2
buildtools/build-release

@ -82,6 +82,7 @@ def main():
containerfiles.append(f'{basepath}/{args.target}')
elif args.target == 'all':
for root,dirnames,filenames in os.walk(basepath):
filenames.sort()
for filename in filenames:
if should_skip(filename):
continue
@ -89,6 +90,7 @@ def main():
containerfiles.append(containerfile)
else:
for root,dirnames,filenames in os.walk(basepath):
filenames.sort()
for filename in filenames:
if args.target not in filename:
continue

9
buildtools/containerfiles/debian.10.arm64

@ -1,9 +0,0 @@
FROM --platform=linux/arm64 debian:10 as build
COPY install-build-pkgs build-mergerfs /tmp/
RUN /tmp/install-build-pkgs
ARG BUILD_TIMESTAMP=0
ARG BRANCH=master
RUN /tmp/build-mergerfs $BRANCH
FROM scratch
COPY --from=build /build/ /

2
buildtools/containerfiles/debian.10.armhf → buildtools/containerfiles/fedora.43.amd64

@ -1,4 +1,4 @@
FROM --platform=linux/armhf debian:10 as build
FROM --platform=linux/amd64 fedora:43 as build
COPY install-build-pkgs build-mergerfs /tmp/
RUN /tmp/install-build-pkgs
ARG BUILD_TIMESTAMP=0

2
buildtools/containerfiles/debian.10.i386 → buildtools/containerfiles/fedora.43.arm64

@ -1,4 +1,4 @@
FROM --platform=linux/i386 debian:10 as build
FROM --platform=linux/arm64 fedora:43 as build
COPY install-build-pkgs build-mergerfs /tmp/
RUN /tmp/install-build-pkgs
ARG BUILD_TIMESTAMP=0

2
buildtools/containerfiles/centos.10.amd64 → buildtools/containerfiles/rockylinux.10.amd64

@ -1,4 +1,4 @@
FROM --platform=linux/amd64 quay.io/centos/centos:10 as build
FROM --platform=linux/amd64 quay.io/rockylinux/rockylinux:10 as build
COPY install-build-pkgs build-mergerfs /tmp/
RUN /tmp/install-build-pkgs
ARG BUILD_TIMESTAMP=0

2
buildtools/containerfiles/centos.10.arm64 → buildtools/containerfiles/rockylinux.10.arm64

@ -1,4 +1,4 @@
FROM --platform=linux/arm64 quay.io/centos/centos:10 as build
FROM --platform=linux/arm64 quay.io/rockylinux/rockylinux:10 as build
COPY install-build-pkgs build-mergerfs /tmp/
RUN /tmp/install-build-pkgs
ARG BUILD_TIMESTAMP=0

2
buildtools/containerfiles/debian.10.amd64 → buildtools/containerfiles/rockylinux.10.riscv64

@ -1,4 +1,4 @@
FROM --platform=linux/amd64 debian:10 as build
FROM --platform=linux/riscv64 quay.io/rockylinux/rockylinux:10 as build
COPY install-build-pkgs build-mergerfs /tmp/
RUN /tmp/install-build-pkgs
ARG BUILD_TIMESTAMP=0

2
buildtools/containerfiles/rockylinux.8.amd64

@ -1,4 +1,4 @@
FROM --platform=linux/amd64 rockylinux:8 as build
FROM --platform=linux/amd64 quay.io/rockylinux/rockylinux:8 as build
COPY install-build-pkgs build-mergerfs /tmp/
RUN /tmp/install-build-pkgs
ARG BUILD_TIMESTAMP=0

2
buildtools/containerfiles/rockylinux.8.arm64

@ -1,4 +1,4 @@
FROM --platform=linux/arm64 rockylinux:8 as build
FROM --platform=linux/arm64 quay.io/rockylinux/rockylinux:8 as build
COPY install-build-pkgs build-mergerfs /tmp/
RUN /tmp/install-build-pkgs
ARG BUILD_TIMESTAMP=0

2
buildtools/containerfiles/rockylinux.8.armhf

@ -1,4 +1,4 @@
FROM --platform=linux/armhf rockylinux:8 as build
FROM --platform=linux/armhf quay.io/rockylinux/rockylinux:8 as build
COPY install-build-pkgs build-mergerfs /tmp/
RUN /tmp/install-build-pkgs
ARG BUILD_TIMESTAMP=0

2
buildtools/containerfiles/rockylinux.8.i386

@ -1,4 +1,4 @@
FROM --platform=linux/i386 rockylinux:8 as build
FROM --platform=linux/i386 quay.io/rockylinux/rockylinux:8 as build
COPY install-build-pkgs build-mergerfs /tmp/
RUN /tmp/install-build-pkgs
ARG BUILD_TIMESTAMP=0

2
buildtools/containerfiles/rockylinux.9.amd64

@ -1,4 +1,4 @@
FROM --platform=linux/amd64 rockylinux:9 as build
FROM --platform=linux/amd64 quay.io/rockylinux/rockylinux:9 as build
COPY install-build-pkgs build-mergerfs /tmp/
RUN /tmp/install-build-pkgs
ARG BUILD_TIMESTAMP=0

2
buildtools/containerfiles/rockylinux.9.arm64

@ -1,4 +1,4 @@
FROM --platform=linux/arm64 rockylinux:9 as build
FROM --platform=linux/arm64 quay.io/rockylinux/rockylinux:9 as build
COPY install-build-pkgs build-mergerfs /tmp/
RUN /tmp/install-build-pkgs
ARG BUILD_TIMESTAMP=0

2
buildtools/containerfiles/rockylinux.9.armhf

@ -1,4 +1,4 @@
FROM --platform=linux/armhf rockylinux:9 as build
FROM --platform=linux/armhf quay.io/rockylinux/rockylinux:9 as build
COPY install-build-pkgs build-mergerfs /tmp/
RUN /tmp/install-build-pkgs
ARG BUILD_TIMESTAMP=0

2
buildtools/containerfiles/rockylinux.9.i386

@ -1,4 +1,4 @@
FROM --platform=linux/i386 rockylinux:9 as build
FROM --platform=linux/i386 quay.io/rockylinux/rockylinux:9 as build
COPY install-build-pkgs build-mergerfs /tmp/
RUN /tmp/install-build-pkgs
ARG BUILD_TIMESTAMP=0

13
buildtools/containerfiles/static.riscv64

@ -0,0 +1,13 @@
ARG BUILD_TIMESTAMP=0
FROM --platform=linux/riscv64 alpine:latest as build
COPY install-build-pkgs /tmp/
RUN /tmp/install-build-pkgs
ARG BRANCH=master
RUN git clone https://github.com/trapexit/mergerfs /tmp/mergerfs -b "${BRANCH}"
WORKDIR /tmp/mergerfs
RUN make NDEBUG=1 LTO=1 STATIC=1 DESTDIR=/tmp -j$(nproc) install
RUN mkdir /build
RUN tar cvfz /build/mergerfs-static-linux_riscv64.tar.gz --directory=/tmp usr sbin
FROM scratch
COPY --from=build /build/ /

282
buildtools/git2debcl

@ -1,4 +1,4 @@
#!/usr/bin/env python3
#!/bin/sh
# Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
@ -14,99 +14,189 @@
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
import sys
import subprocess
import argparse
def call(args):
return subprocess.Popen(args,stdout=subprocess.PIPE).communicate()[0].decode()
def git_tags():
args = ["git", "tag", '-l']
tags = call(args)
tags = [[int(X) for X in tag.split(".")] for tag in tags.split()]
tags.sort()
tags.reverse()
tags = [".".join([str(X) for X in tag]) for tag in tags]
return tags
def git_log(fromtag,totag):
args = ['git','log','--no-merges','--oneline',fromtag+'...'+totag]
return call(args).strip().split('\n')
def git_author_and_time(tag):
args = ['git','log','-1','--format=-- %an <%ae> %cD',tag]
return call(args).strip()
def git_version():
args = ['git','describe','--always','--tags','--dirty']
return call(args).strip()
def guess_distro():
try:
args = ['lsb_release','-i','-s']
return call(args).strip().lower()
except:
return 'unknown'
def guess_codename():
try:
args = ['lsb_release','-c','-s']
return call(args).strip().lower()
except:
return 'unknown'
def main():
parser = argparse.ArgumentParser(description='Generated debian/changelog from git log')
parser.add_argument('--name',type=str,help='Name of package',required=True)
parser.add_argument('--version',type=str,help='Place in git history to include upto',default='::guess::')
parser.add_argument('--distro',type=str,help='Distribution name',default='::guess::')
parser.add_argument('--codename',type=str,help='Distribution codename',default='::guess::')
parser.add_argument('--urgency',type=str,help='Urgency',default='medium')
args = parser.parse_args()
if args.distro == '::guess::':
args.distro = guess_distro()
if args.codename == '::guess::':
args.codename = guess_codename()
versuffix = "~"+args.distro+"-"+args.codename
if args.version == '::guess::':
args.version = git_version()
tags = git_tags()
if args.version in tags:
idx = tags.index(args.version)
tags = tags[idx:]
tags = list(zip(tags,tags))
else:
tags = list(zip(tags,tags))
tags.insert(0,(args.version,'HEAD'))
for i in range(0,len(tags)):
tags[i] = (tags[i][0] + versuffix,tags[i][1])
tag = tags[0]
for prev in tags[1:]:
lines = git_log(tag[1],prev[1])
if lines == ['']:
tag = prev
# Default values
NAME=""
VERSION="::guess::"
DISTRO="::guess::"
CODENAME="::guess::"
URGENCY="medium"
# Function to display usage
usage() {
cat << EOF
Usage: $0 --name NAME [OPTIONS]
Generated debian/changelog from git log
Options:
--name NAME Name of package (required)
--version VERSION Place in git history to include upto (default: ::guess::)
--distro DISTRO Distribution name (default: ::guess::)
--codename NAME Distribution codename (default: ::guess::)
--urgency URGENCY Urgency (default: medium)
-h, --help Show this help message
EOF
exit 1
}
# Parse command line arguments
while [ $# -gt 0 ]; do
case "$1" in
--name)
NAME="$2"
shift 2
;;
--version)
VERSION="$2"
shift 2
;;
--distro)
DISTRO="$2"
shift 2
;;
--codename)
CODENAME="$2"
shift 2
;;
--urgency)
URGENCY="$2"
shift 2
;;
-h|--help)
usage
;;
*)
echo "Unknown option: $1" >&2
usage
;;
esac
done
# Check required arguments
if [ -z "$NAME" ]; then
echo "Error: --name is required" >&2
usage
fi
# Function to get git tags sorted in reverse order
git_tags() {
git tag -l | sort -rV
}
# Function to get git log between two tags
git_log() {
local fromtag="$1"
local totag="$2"
git log --no-merges --oneline "${fromtag}...${totag}" 2>/dev/null
}
# Function to get author and time for a tag
git_author_and_time() {
local tag="$1"
git log -1 --format="-- %an <%ae> %cD" "$tag"
}
# Function to get git version
git_version() {
git describe --always --tags --dirty 2>/dev/null || echo "unknown"
}
# Function to guess distribution
guess_distro() {
if command -v lsb_release >/dev/null 2>&1; then
lsb_release -i -s 2>/dev/null | tr '[:upper:]' '[:lower:]'
else
echo "unknown"
fi
}
# Function to guess codename
guess_codename() {
if command -v lsb_release >/dev/null 2>&1; then
lsb_release -c -s 2>/dev/null | tr '[:upper:]' '[:lower:]'
else
echo "unknown"
fi
}
# Handle guessing of values
if [ "$DISTRO" = "::guess::" ]; then
DISTRO=$(guess_distro)
fi
if [ "$CODENAME" = "::guess::" ]; then
CODENAME=$(guess_codename)
fi
if [ "$VERSION" = "::guess::" ]; then
VERSION=$(git_version)
fi
# Version suffix
VERSUFFIX="~${DISTRO}-${CODENAME}"
# Get all tags
TAGS=$(git_tags)
# Create temporary file for tag pairs
TMPFILE=$(mktemp)
trap 'rm -f "$TMPFILE"' EXIT
# Check if version is in tags
if echo "$TAGS" | grep -q "^${VERSION}$"; then
# If version is a tag, start from that tag
echo "$TAGS" | awk -v ver="$VERSION" 'BEGIN{found=0} {if($0==ver)found=1; if(found)print}' > "$TMPFILE"
else
# If version is not a tag, use HEAD as starting point
echo "$VERSION HEAD" > "$TMPFILE"
echo "$TAGS" >> "$TMPFILE"
fi
# Process tags and generate changelog
PREV_TAG=""
PREV_REF=""
FIRST=1
while IFS= read -r line; do
if [ -z "$line" ]; then
continue
fi
# Handle the special case of VERSION HEAD
if [ "$line" = "$VERSION HEAD" ]; then
TAG="$VERSION"
REF="HEAD"
else
TAG="$line"
REF="$line"
fi
if [ -n "$PREV_TAG" ]; then
# Get log entries between current and previous tag
LOG_ENTRIES=$(git_log "$REF" "$PREV_REF")
# Skip if no changes
if [ -z "$LOG_ENTRIES" ] || [ "$LOG_ENTRIES" = "" ]; then
PREV_TAG="$TAG"
PREV_REF="$REF"
continue
print('{0} ({1}) {2}; urgency={3}\n'.format(args.name,tag[0],args.codename,args.urgency))
for line in lines:
print(" * " + line)
authorandtime = git_author_and_time(tag[1])
print(' {0}\n'.format(authorandtime))
tag = prev
if __name__ == "__main__":
main()
fi
# Print package header
printf "%s (%s%s) %s; urgency=%s\n\n" "$NAME" "$PREV_TAG" "$VERSUFFIX" "$CODENAME" "$URGENCY"
# Print each log entry
echo "$LOG_ENTRIES" | while IFS= read -r entry; do
if [ -n "$entry" ]; then
printf " * %s\n" "$entry"
fi
done
# Print author and time
AUTHOR_TIME=$(git_author_and_time "$PREV_REF")
printf "\n %s\n\n" "$AUTHOR_TIME"
fi
PREV_TAG="$TAG"
PREV_REF="$REF"
done < "$TMPFILE"

23
buildtools/install-build-pkgs

@ -13,37 +13,28 @@ if [ -e /usr/bin/apt-get ]; then
debhelper \
lsb-release \
fakeroot
apt-get -qy --force-yes --no-install-suggests --no-install-recommends install python
apt-get -qy --force-yes --no-install-suggests --no-install-recommends install python3
elif [ -e /usr/bin/dnf ]; then
dnf -y update
dnf -y install \
git rpm-build gcc-c++ make which python3
git rpm-build gcc-c++ make which libatomic
dnf -y install lsb_release || true
elif [ -e /usr/bin/yum ]; then
yum -y update
yum -y install \
git rpm-build gcc-c++ make which \
python python-argparse
git rpm-build gcc-c++ make which
yum -y install lsb_release || true
yum -y install centos-release-scl
yum -y install devtoolset-9-gcc\*
elif [ -e /usr/bin/zypper ]; then
zypper update -y
zypper install -y \
git rpm-build gcc-c++ make which \
python
git rpm-build gcc-c++ make which \
lsb_release
elif [ -e /sbin/apk ]; then
apk add \
abuild git gcc g++ make \
linux-headers
linux-headers lsb-release
elif [ -e /usr/sbin/pkg ]; then
pkg install \
git gmake gcc
fi
if [ ! -e /usr/bin/python ]; then
if [ -e /usr/bin/python3 ]; then
ln -s /usr/bin/python3 /usr/bin/python
elif [ -e /usr/bin/python2 ]; then
ln -s /usr/bin/python2 /usr/bin/python
fi
fi

19
buildtools/install-build-tools

@ -0,0 +1,19 @@
#!/bin/sh
if [ -e /usr/bin/apt-get ]; then
export DEBIAN_FRONTEND=noninteractive
apt-get -qy update
apt-get -qy --force-yes --no-install-suggests --no-install-recommends install \
qemu-user-static \
podman
elif [ -e /usr/bin/dnf ]; then
dnf -y update
dnf -y install \
qemu-user-static \
podman
elif [ -e /sbin/apk ]; then
apk add \
python3 \
qemu-user-static \
podman
fi

4
buildtools/update-version

@ -9,10 +9,12 @@ if [ "${VERSION}" = "" ]; then
VERSION="unknown"
fi
echo "version = ${VERSION}"
echo -n "${VERSION}" > VERSION
grep -q \"${VERSION}\" src/version.hpp
grep -sq \"${VERSION}\" src/version.hpp
RV=$?
if [ $RV -ne 0 ]; then
echo "Writing 'src/version.hpp'"
echo "#pragma once" > src/version.hpp
echo "static const char MERGERFS_VERSION[] = \"${VERSION}\";" >> src/version.hpp
fi

10
debian/rules

@ -4,10 +4,10 @@
export DH_VERBOSE=1
%:
dh $@ --parallel --max-parallel=6
override_dh_strip:
dh_strip --no-automatic-dbgsym
dh $@
override_dh_auto_install:
$(MAKE) DESTDIR=$(CURDIR)/debian/mergerfs PREFIX=/usr install
$(MAKE) \
DESTDIR=$(CURDIR)/debian/mergerfs \
PREFIX=/usr \
install

139
libfuse/Makefile

@ -1,4 +1,11 @@
VERSION = 2.9.7-mergerfs_2.30.0
AR ?= ar
CHMOD ?= chmod
CHOWN ?= chown
INSTALL ?= install
MKDIR ?= mkdir
RM ?= rm
STRIP ?= strip
TOUCH ?= touch
OS := $(shell uname -s)
ifeq ($(OS),Linux)
@ -12,7 +19,7 @@ endif
ifeq ($(NDEBUG),1)
OPT_FLAGS := -O2 -DNDEBUG
else
OPT_FLAGS := -O0 -DDEBUG -g
OPT_FLAGS := -O0 -g -DDEBUG -fno-omit-frame-pointer
endif
ifeq ($(LTO),1)
@ -21,21 +28,22 @@ else
LTO_FLAGS :=
endif
DESTDIR =
PREFIX = /usr/local
EXEC_PREFIX = $(PREFIX)
DATAROOTDIR = $(PREFIX)/share
DATADIR = $(DATAROOTDIR)
BINDIR = $(EXEC_PREFIX)/bin
SBINDIR = /sbin
MANDIR = $(DATAROOTDIR)/man
MAN1DIR = $(MANDIR)/man1
# https://www.gnu.org/prep/standards/html_node/Directory-Variables.html
DESTDIR ?=
PREFIX ?= /usr/local
EXEC_PREFIX ?= $(PREFIX)
DATAROOTDIR ?= $(PREFIX)/share
DATADIR ?= $(DATAROOTDIR)
BINDIR ?= $(EXEC_PREFIX)/bin
SBINDIR ?= /sbin
MANDIR ?= $(DATAROOTDIR)/man
MAN1DIR ?= $(MANDIR)/man1
INSTALLBINDIR = $(DESTDIR)$(BINDIR)
INSTALLSBINDIR = $(DESTDIR)$(SBINDIR)
INSTALLMAN1DIR = $(DESTDIR)$(MAN1DIR)
INSTALLBINDIR ?= $(DESTDIR)$(BINDIR)
INSTALLSBINDIR ?= $(DESTDIR)$(SBINDIR)
INSTALLMAN1DIR ?= $(DESTDIR)$(MAN1DIR)
AR ?= ar
BUILDDIR := build
SRC_C = \
lib/buffer.c \
@ -48,7 +56,7 @@ SRC_C = \
lib/fuse_signals.c \
lib/helper.c \
lib/mount.c
SRC_CPP = \
SRC_CXX = \
lib/fuse.cpp \
lib/cpu.cpp \
lib/fuse_config.cpp \
@ -59,90 +67,91 @@ SRC_CPP = \
lib/node.cpp \
lib/maintenance_thread.cpp
OBJS_C = $(SRC_C:lib/%.c=build/%.o)
OBJS_CPP = $(SRC_CPP:lib/%.cpp=build/%.o)
DEPS_C = $(SRC_C:lib/%.c=build/%.d)
DEPS_CPP = $(SRC_CPP:lib/%.cpp=build/%.d)
OBJS_C = $(SRC_C:lib/%.c=$(BUILDDIR)/%.o)
OBJS_CXX = $(SRC_CXX:lib/%.cpp=$(BUILDDIR)/%.o)
DEPS_C = $(SRC_C:lib/%.c=$(BUILDDIR)/%.d)
DEPS_CXX = $(SRC_CXX:lib/%.cpp=$(BUILDDIR)/%.d)
CPPFLAGS ?=
CFLAGS ?= \
$(OPT_FLAGS)
CFLAGS := \
${CFLAGS} \
$(OPT_FLAGS) \
$(LTO_FLAGS) \
-std=gnu99 \
-Wall \
-pipe \
-MMD
-pipe
override CFLAGS += \
-std=gnu99 \
-MMD \
-MP
CXXFLAGS ?= \
$(OPT_FLAGS)
CXXFLAGS := \
${CXXFLAGS} \
$(OPT_FLAGS) \
$(LTO_FLAGS) \
-std=c++17 \
-Wall \
-pipe \
-MMD
FUSERMOUNT_DIR = $(BINDIR)
FUSE_FLAGS = \
-pipe
override CXXFLAGS += \
-std=c++17 \
-MMD \
-MP
FUSERMOUNT_DIR := $(BINDIR)
FUSE_FLAGS := \
-Iinclude \
-Ibuild \
-I$(BUILDDIR) \
-D_REENTRANT \
-D_FILE_OFFSET_BITS=64 \
-DFUSERMOUNT_DIR=\"$(FUSERMOUNT_DIR)\"
LDFLAGS := \
${LDFLAGS} \
LDFLAGS ?=
LDLIBS := \
-lrt \
-latomic \
-pthread
all: build/libfuse.a $(UTILS)
build/config.h: build/stamp
ecfd/build | tee build/config.h
build/stamp:
mkdir -p build
touch $@
all: $(BUILDDIR)/libfuse.a $(UTILS)
objects: build/config.h
$(MAKE) $(OBJS_C) $(OBJS_CPP)
$(BUILDDIR)/stamp:
$(MKDIR) -p $(BUILDDIR)
$(TOUCH) $@
build/libfuse.a: objects
${AR} rcs build/libfuse.a $(OBJS_C) $(OBJS_CPP)
$(BUILDDIR)/libfuse.a: $(OBJS_C) $(OBJS_CXX)
$(AR) rcs $(BUILDDIR)/libfuse.a $(OBJS_C) $(OBJS_CXX)
.PHONY: utils
utils: mergerfs-fusermount mount.mergerfs
build/mergerfs-fusermount: build/config.h util/fusermount.c lib/mount_util.c
$(CC) $(CFLAGS) $(FUSE_FLAGS) -Ilib -o build/mergerfs-fusermount util/fusermount.c lib/mount_util.c
$(BUILDDIR)/mergerfs-fusermount: util/fusermount.c lib/mount_util.c
$(CC) $(CFLAGS) $(FUSE_FLAGS) -Ilib -o $(BUILDDIR)/mergerfs-fusermount util/fusermount.c lib/mount_util.c
mergerfs-fusermount: build/mergerfs-fusermount
mergerfs-fusermount: $(BUILDDIR)/mergerfs-fusermount
build/mount.mergerfs: build/libfuse.a util/mount.mergerfs.c
$(CC) $(CFLAGS) $(FUSE_FLAGS) -o build/mount.mergerfs util/mount.mergerfs.c build/libfuse.a $(LDFLAGS)
$(BUILDDIR)/mount.mergerfs: $(BUILDDIR)/libfuse.a util/mount.mergerfs.c
$(CC) $(CFLAGS) $(FUSE_FLAGS) -o $(BUILDDIR)/mount.mergerfs util/mount.mergerfs.c $(BUILDDIR)/libfuse.a $(LDFLAGS)
mount.mergerfs: build/mount.mergerfs
mount.mergerfs: $(BUILDDIR)/mount.mergerfs
build/%.o: lib/%.c
$(BUILDDIR)/%.o: lib/%.c | $(BUILDDIR)/stamp
$(CC) $(CFLAGS) $(FUSE_FLAGS) -c $< -o $@
build/%.o: lib/%.cpp
$(BUILDDIR)/%.o: lib/%.cpp | $(BUILDDIR)/stamp
$(CXX) $(CXXFLAGS) $(FUSE_FLAGS) -c $< -o $@
.PHONY: clean
clean:
rm -rf build
$(RM) -rf $(BUILDDIR)
.PHONY: distclean
distclean: clean
.PHONY: strip
strip:
strip --strip-all build/mount.mergerfs
strip --strip-all build/mergerfs-fusermount
$(STRIP) --strip-all $(BUILDDIR)/mount.mergerfs
$(STRIP) --strip-all $(BUILDDIR)/mergerfs-fusermount
install-utils: mergerfs-fusermount mount.mergerfs strip
install -D build/mergerfs-fusermount "$(INSTALLBINDIR)/mergerfs-fusermount"
install -D build/mount.mergerfs "$(INSTALLSBINDIR)/mount.mergerfs"
chown root:root "$(INSTALLBINDIR)/mergerfs-fusermount"
chmod u+s "$(INSTALLBINDIR)/mergerfs-fusermount"
$(INSTALL) -D $(BUILDDIR)/mergerfs-fusermount "$(INSTALLBINDIR)/mergerfs-fusermount"
$(INSTALL) -D $(BUILDDIR)/mount.mergerfs "$(INSTALLSBINDIR)/mount.mergerfs"
$(CHOWN) root:root "$(INSTALLBINDIR)/mergerfs-fusermount"
$(CHMOD) u+s "$(INSTALLBINDIR)/mergerfs-fusermount"
install: $(INSTALLUTILS)
.PHONY: objects strip utils install install-utils
-include $(DEPS_C) $(DEPS_CPP)
-include $(DEPS_C) $(DEPS_CXX)

17
libfuse/ecfd/LICENSE

@ -1,17 +0,0 @@
/*
ISC License
Copyright (c) 2018, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

16
libfuse/ecfd/README.md

@ -1,16 +0,0 @@
# ecfd: embeddable C feature discovery
This is a simple script and set of tests to help with what would traditionally be the `configure` step of most C/C++. It is intended to be simple to be embedded into a project and only depends on the C compiler and /bin/sh.
## USAGE
First copy `ecfd` into your project. Next simply call the build script which will run the tests and output a `config.` style file to `stdout`. Compile errors will output to `stderr` which can be used to understand why they aren't working.
```
$ ./ecfd/build > include/config.h
```
## TESTS
Each test is in a single module. The build script will try to compile each module and on success will execute the program. If anything is printed to `stdout` it will be appended to the `#define` printed to the build script's `stdout`. If the compilation fails nothing will be printed. Look at the tests directory for examples.

32
libfuse/ecfd/build

@ -1,32 +0,0 @@
#!/bin/sh
PWD=$(pwd)
BASEPATH="${PWD}/${0%/*}"
CC=${CC:-cc}
OUTPUT="/dev/null"
echo "#ifndef CONFIG_H_INCLUDED"
echo "#define CONFIG_H_INCLUDED"
echo
IFS=
for file in "${BASEPATH}/tests/"*.c
do
binary="${file%.c}"
basename=$(basename ${binary})
${CC} -o "${binary}" "${file}" 1>&2
if [ $? -eq 0 ]; then
STDOUT=$(${binary})
if [ "${STDOUT}" != "" ]; then
echo "#define ${basename} ${STDOUT}"
else
echo "#define ${basename}"
fi
rm -f "${binary}"
fi
done
echo
echo "#endif"

10
libfuse/ecfd/tests/HAVE_FORK.c

@ -1,10 +0,0 @@
#include <sys/types.h>
#include <unistd.h>
int
main(void)
{
(void)fork;
return 0;
}

7
libfuse/ecfd/tests/HAVE_MALLOC_TRIM.c

@ -1,7 +0,0 @@
#include <malloc.h>
int
main()
{
malloc_trim(0);
}

14
libfuse/ecfd/tests/HAVE_STRUCT_STAT_ST_ATIM.c

@ -1,14 +0,0 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int
main(int argc,
char *argv[])
{
struct stat st;
(void)st.st_atim;
return 0;
}

11
libfuse/ecfd/tests/HAVE_UTIMENSAT.c

@ -1,11 +0,0 @@
#include <fcntl.h>
#include <sys/stat.h>
int
main(int argc,
char *argv[])
{
(void)utimensat;
return 0;
}

4
libfuse/ecfd/tests/static_assert.h

@ -1,4 +0,0 @@
#pragma once
#define STATIC_ASSERT(condition) \
((void)sizeof(char[1 - 2*!(condition)]))

13
libfuse/include/stat_utils.h

@ -1,17 +1,16 @@
#pragma once
#include "config.h"
#ifdef HAVE_STRUCT_STAT_ST_ATIM
#ifdef __linux__
#define ST_ATIM_NSEC(ST) ((ST)->st_atim.tv_nsec)
#define ST_CTIM_NSEC(ST) ((ST)->st_ctim.tv_nsec)
#define ST_MTIM_NSEC(ST) ((ST)->st_mtim.tv_nsec)
#elif defined HAVE_STRUCT_STAT_ST_ATIMESPEC
#elif defined __FreeBSD__
#define ST_ATIM_NSEC(ST) ((ST)->st_atimespec.tv_nsec)
#define ST_CTIM_NSEC(ST) ((ST)->st_ctimespec.tv_nsec)
#define ST_MTIM_NSEC(ST) ((ST)->st_mtimespec.tv_nsec)
#else
#define ST_ATIM_NSEC(ST) 0
#define ST_CTIM_NSEC(ST) 0
#define ST_MTIM_NSEC(ST) 0
#error "Unsupported platform for st_{a,c,m}time nanosecond"
/* #define ST_ATIM_NSEC(ST) 0 */
/* #define ST_CTIM_NSEC(ST) 0 */
/* #define ST_MTIM_NSEC(ST) 0 */
#endif

1
libfuse/lib/buffer.c

@ -8,7 +8,6 @@
#define _GNU_SOURCE
#include "config.h"
#include "fuse_i.h"
#include "fuse_lowlevel.h"
#include <string.h>

1014
libfuse/lib/debug.cpp
File diff suppressed because it is too large
View File

23
libfuse/lib/fuse.cpp

@ -11,18 +11,18 @@
#define _GNU_SOURCE
#endif
#include "syslog.hpp"
#include "crc32b.h"
#include "khash.h"
#include "kvec.h"
#include "mutex.hpp"
#include "node.hpp"
#include "config.h"
#include "fuse_dirents.h"
#include "fuse_i.h"
#include "fuse_kernel.h"
#include "fuse_lowlevel.h"
#include "fuse_misc.h"
#include "fuse_opt.h"
#include "fuse_pollhandle.h"
#include "fuse_msgbuf.hpp"
@ -51,11 +51,10 @@
#include <sys/param.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <syslog.h>
#include <time.h>
#include <unistd.h>
#ifdef HAVE_MALLOC_TRIM
#ifdef __GLIBC__
#include <malloc.h>
#endif
@ -1848,7 +1847,6 @@ fuse_lib_setattr(fuse_req_t req,
f->fs->op.truncate(path,arg->size) :
f->fs->op.ftruncate(fh,arg->size));
#ifdef HAVE_UTIMENSAT
if(!err && (arg->valid & (FATTR_ATIME | FATTR_MTIME)))
{
struct timespec tv[2];
@ -1872,9 +1870,7 @@ fuse_lib_setattr(fuse_req_t req,
f->fs->op.utimens(path,tv) :
f->fs->op.futimens(fh,tv));
}
else
#endif
if(!err && ((arg->valid & (FATTR_ATIME|FATTR_MTIME)) == (FATTR_ATIME|FATTR_MTIME)))
else if(!err && ((arg->valid & (FATTR_ATIME|FATTR_MTIME)) == (FATTR_ATIME|FATTR_MTIME)))
{
struct timespec tv[2];
tv[0].tv_sec = arg->atime;
@ -3971,7 +3967,7 @@ static
void
fuse_malloc_trim(void)
{
#ifdef HAVE_MALLOC_TRIM
#ifdef __GLIBC__
malloc_trim(1024 * 1024);
#endif
}
@ -4003,9 +3999,8 @@ fuse_invalidate_all_nodes()
}
mutex_unlock(&f->lock);
syslog(LOG_INFO,
"invalidating %ld file entries",
names.size());
SysLog::info("invalidating {} file entries",
names.size());
for(auto &name : names)
{
fuse_lowlevel_notify_inval_entry(f->se->ch,
@ -4018,7 +4013,7 @@ fuse_invalidate_all_nodes()
void
fuse_gc()
{
syslog(LOG_INFO,"running thorough garbage collection");
SysLog::info("running thorough garbage collection");
node_gc();
msgbuf_gc();
fuse_malloc_trim();
@ -4027,7 +4022,7 @@ fuse_gc()
void
fuse_gc1()
{
syslog(LOG_INFO,"running basic garbage collection");
SysLog::info("running basic garbage collection");
node_gc1();
msgbuf_gc_10percent();
fuse_malloc_trim();

1
libfuse/lib/fuse_loop.cpp

@ -13,7 +13,6 @@
#include "fuse_i.h"
#include "fuse_kernel.h"
#include "fuse_lowlevel.h"
#include "fuse_misc.h"
#include "fuse_config.hpp"
#include "fuse_msgbuf.hpp"

5
libfuse/lib/fuse_lowlevel.cpp

@ -13,14 +13,13 @@
#include "mutex.hpp"
#include "lfmp.h"
#include "config.h"
#include "debug.hpp"
#include "fuse_i.h"
#include "fuse_kernel.h"
#include "fuse_msgbuf.hpp"
#include "fuse_opt.h"
#include "fuse_misc.h"
#include "fuse_pollhandle.h"
#include "fuse_msgbuf.hpp"
#include "stat_utils.h"
#include <stdio.h>
#include <stdlib.h>

49
libfuse/lib/fuse_misc.h

@ -1,49 +0,0 @@
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB
*/
#pragma once
#include "config.h"
#include <pthread.h>
/*
Versioned symbols cannot be used in some cases because it
- confuse the dynamic linker in uClibc
- not supported on MacOSX (in MachO binary format)
*/
#if (!defined(__UCLIBC__) && !defined(__APPLE__))
#define FUSE_SYMVER(x) __asm__(x)
#else
#define FUSE_SYMVER(x)
#endif
#ifdef HAVE_STRUCT_STAT_ST_ATIM
/* Linux */
#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atim.tv_nsec)
#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctim.tv_nsec)
#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtim.tv_nsec)
#define ST_ATIM_NSEC_SET(stbuf,val) ((stbuf)->st_atim.tv_nsec = (val))
#define ST_CTIM_NSEC_SET(stbuf,val) ((stbuf)->st_ctim.tv_nsec = (val))
#define ST_MTIM_NSEC_SET(stbuf,val) ((stbuf)->st_mtim.tv_nsec = (val))
#elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC)
/* FreeBSD */
#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atimespec.tv_nsec)
#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctimespec.tv_nsec)
#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtimespec.tv_nsec)
#define ST_ATIM_NSEC_SET(stbuf,val) ((stbuf)->st_atimespec.tv_nsec = (val))
#define ST_CTIM_NSEC_SET(stbuf,val) ((stbuf)->st_ctimespec.tv_nsec = (val))
#define ST_MTIM_NSEC_SET(stbuf,val) ((stbuf)->st_mtimespec.tv_nsec = (val))
#else
#define ST_ATIM_NSEC(stbuf) 0
#define ST_CTIM_NSEC(stbuf) 0
#define ST_MTIM_NSEC(stbuf) 0
#define ST_ATIM_NSEC_SET(stbuf,val) do { } while (0)
#define ST_CTIM_NSEC_SET(stbuf,val) do { } while (0)
#define ST_MTIM_NSEC_SET(stbuf,val) do { } while (0)
#endif

1
libfuse/lib/fuse_opt.c

@ -7,7 +7,6 @@
*/
#include "fuse_opt.h"
#include "fuse_misc.h"
#include <stdio.h>
#include <stdlib.h>

1
libfuse/lib/fuse_session.c

@ -7,7 +7,6 @@
*/
#include "fuse_i.h"
#include "fuse_misc.h"
#include "fuse_kernel.h"
#include <assert.h>

2
libfuse/lib/helper.c

@ -6,9 +6,7 @@
See the file COPYING.LIB.
*/
#include "config.h"
#include "fuse_i.h"
#include "fuse_misc.h"
#include "fuse_opt.h"
#include "fuse_lowlevel.h"

6
libfuse/lib/mount_generic.c

@ -6,9 +6,7 @@
See the file COPYING.LIB.
*/
#include "config.h"
#include "fuse_i.h"
#include "fuse_misc.h"
#include "fuse_opt.h"
#include "mount_util.h"
@ -41,10 +39,6 @@
#define FUSERMOUNT_PROG "fusermount"
#define FUSE_COMMFD_ENV "_FUSE_COMMFD"
#ifndef HAVE_FORK
#define fork() vfork()
#endif
#ifndef MS_DIRSYNC
#define MS_DIRSYNC 128
#endif

7
libfuse/lib/pin_threads.cpp

@ -1,6 +1,6 @@
#include "pin_threads.hpp"
#include <syslog.h>
#include "syslog.hpp"
void
PinThreads::R1L(const CPU::ThreadIdVec threads_)
@ -211,7 +211,6 @@ PinThreads::pin(const CPU::ThreadIdVec read_threads_,
if(type_ == "R1PPSP")
return PinThreads::R1PPSP(read_threads_,process_threads_);
syslog(LOG_WARNING,
"Invalid pin-threads type, ignoring: %s",
type_.c_str());
SysLog::warning("Invalid pin-threads type, ignoring: {}",
type_);
}

3
libfuse/util/fusermount.c

@ -8,7 +8,6 @@
/* This program does the mounting and unmounting of FUSE filesystems */
#define _GNU_SOURCE /* for clone */
#include <config.h>
#include "mount_util.h"
#include <stdio.h>
@ -30,7 +29,7 @@
#include <sys/utsname.h>
#include <sched.h>
#define FUSE_COMMFD_ENV "_FUSE_COMMFD"
#define FUSE_COMMFD_ENV "_FUSE_COMMFD"
#define FUSE_DEV_OLD "/proc/fs/fuse/dev"
#define FUSE_DEV_NEW "/dev/fuse"

6
mergerfs.spec

@ -13,9 +13,9 @@ BuildRequires: gcc-c++
# rpmbuild driven by the Makefile uses git to generate a version number
BuildRequires: git
Requires: fuse
%global debug_package %{nil}
%undefine _debuginfo_subpackages
%global _enable_debug_packages 0
%prep
%setup -q
@ -26,7 +26,7 @@ management of files across numerous commodity storage devices. It is
similar to mhddfs, unionfs, and aufs.
%build
make %{?_smp_mflags}
make %{?_smp_mflags} CFLAGS="%{optflags}" CXXFLAGS="%{optflags}" LDFLAGS="%{__global_ldflags}"
%install
make install PREFIX=%{_prefix} DESTDIR=%{buildroot}

8
src/error.hpp

@ -30,4 +30,12 @@ public:
return *this;
}
bool
operator==(int v_)
{
if(_err.has_value())
return (_err.value() == v_);
return false;
}
};

8
src/fuse_listxattr.cpp

@ -34,13 +34,17 @@ ssize_t
_listxattr_size(const std::vector<Branch*> &branches_,
const char *fusepath_)
{
ssize_t rv;
ssize_t size;
std::string fullpath;
if(branches_.empty())
return -ENOENT;
size = 0;
for(const auto branch : branches_)
{
ssize_t rv;
fullpath = fs::path::make(branch->path,fusepath_);
rv = fs::llistxattr(fullpath,NULL,0);
@ -50,7 +54,7 @@ _listxattr_size(const std::vector<Branch*> &branches_,
size += rv;
}
return rv;
return size;
}
static

2
src/fuse_rmdir.cpp

@ -69,7 +69,7 @@ _rmdir_loop(const std::vector<Branch*> &branches_,
{
Err err;
for(auto &branch : branches_)
for(const auto &branch : branches_)
{
err = ::_rmdir_core(branch->path,fusepath_,followsymlinks_);
}

5
src/mergerfs_fsck.cpp

@ -138,6 +138,9 @@ _compare_files(const std::string &mergerfs_path_,
fmt::println(" {}: {}",i,path);
if(st.st_size < 0)
fmt::println(" - err: {}",strerror(-st.st_size));
time_t mtime = st.st_mtime;
std::tm *mtime_tm = std::localtime(&mtime);
fmt::println(" -"
" uid: {};"
" gid: {};"
@ -150,7 +153,7 @@ _compare_files(const std::string &mergerfs_path_,
st.st_mode,
::_file_type(st.st_mode),
st.st_size,
*std::localtime(&st.st_mtime));
*mtime_tm);
}
if(!fix_func_)

56
tools/preload.c

@ -1,7 +1,7 @@
/*
ISC License
Copyright (c) 2024, Antonio SJ Musumeci <trapexit@spawn.link>
Copyright (c) 2025, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -25,14 +25,16 @@
#include <assert.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/xattr.h>
#include <unistd.h>
#include <fcntl.h>
typedef char IOCTL_BUF[4096];
#define IOCTL_APP_TYPE 0xDF
@ -67,13 +69,13 @@ static creat64_func_t _libc_creat64 = NULL;
static
int
get_underlying_filepath(int fd_,
char *filepath_)
get_underlying_filepath(int fd_,
char *filepath_,
size_t filepath_size_)
{
int rv;
strcpy(filepath_,"fullpath");
rv = ioctl(fd_,IOCTL_FILE_INFO,filepath_);
rv = fgetxattr(fd_,"user.mergerfs.fullpath",filepath_,filepath_size_);
if(rv == -1)
return -1;
@ -98,6 +100,7 @@ strip_exec(const char *orig_mode_,
new_mode_[j] = '\0';
}
#ifndef _FILE_OFFSET_BITS
int
open(const char *pathname_,
int flags_,
@ -131,8 +134,8 @@ open(const char *pathname_,
if((st.st_mode & S_IFMT) != S_IFREG)
return fd;
IOCTL_BUF real_pathname;
rv = get_underlying_filepath(fd,real_pathname);
char real_pathname[PATH_MAX];
rv = get_underlying_filepath(fd,real_pathname,sizeof(real_pathname));
if(rv == -1)
return fd;
@ -145,6 +148,7 @@ open(const char *pathname_,
return rv;
}
#endif
int
open64(const char *pathname_,
@ -179,8 +183,8 @@ open64(const char *pathname_,
if((st.st_mode & S_IFMT) != S_IFREG)
return fd;
IOCTL_BUF real_pathname;
rv = get_underlying_filepath(fd,real_pathname);
char real_pathname[PATH_MAX];
rv = get_underlying_filepath(fd,real_pathname,sizeof(real_pathname));
if(rv == -1)
return fd;
@ -194,6 +198,7 @@ open64(const char *pathname_,
return rv;
}
#ifndef _FILE_OFFSET_BITS
int
openat(int dirfd_,
const char *pathname_,
@ -228,8 +233,8 @@ openat(int dirfd_,
if((st.st_mode & S_IFMT) != S_IFREG)
return fd;
IOCTL_BUF real_pathname;
rv = get_underlying_filepath(fd,real_pathname);
char real_pathname[PATH_MAX];
rv = get_underlying_filepath(fd,real_pathname,sizeof(real_pathname));
if(rv == -1)
return fd;
@ -242,6 +247,7 @@ openat(int dirfd_,
return rv;
}
#endif
int
openat64(int dirfd_,
@ -277,8 +283,8 @@ openat64(int dirfd_,
if((st.st_mode & S_IFMT) != S_IFREG)
return fd;
IOCTL_BUF real_pathname;
rv = get_underlying_filepath(fd,real_pathname);
char real_pathname[PATH_MAX];
rv = get_underlying_filepath(fd,real_pathname,sizeof(real_pathname));
if(rv == -1)
return fd;
@ -292,6 +298,7 @@ openat64(int dirfd_,
return rv;
}
#ifndef _FILE_OFFSET_BITS
FILE*
fopen(const char *pathname_,
const char *mode_)
@ -318,8 +325,8 @@ fopen(const char *pathname_,
if((st.st_mode & S_IFMT) != S_IFREG)
return f;
IOCTL_BUF real_pathname;
rv = get_underlying_filepath(fd,real_pathname);
char real_pathname[PATH_MAX];
rv = get_underlying_filepath(fd,real_pathname,sizeof(real_pathname));
if(rv == -1)
return f;
@ -333,6 +340,7 @@ fopen(const char *pathname_,
return f2;
}
#endif
FILE*
fopen64(const char *pathname_,
@ -360,8 +368,8 @@ fopen64(const char *pathname_,
if((st.st_mode & S_IFMT) != S_IFREG)
return f;
IOCTL_BUF real_pathname;
rv = get_underlying_filepath(fd,real_pathname);
char real_pathname[PATH_MAX];
rv = get_underlying_filepath(fd,real_pathname,sizeof(real_pathname));
if(rv == -1)
return f;
@ -376,6 +384,7 @@ fopen64(const char *pathname_,
return f2;
}
#ifndef _FILE_OFFSET_BITS
int
creat(const char *pathname_,
mode_t mode_)
@ -389,8 +398,8 @@ creat(const char *pathname_,
if(fd == -1)
return -1;
IOCTL_BUF real_pathname;
rv = get_underlying_filepath(fd,real_pathname);
char real_pathname[PATH_MAX];
rv = get_underlying_filepath(fd,real_pathname,sizeof(real_pathname));
if(rv == -1)
return fd;
@ -402,6 +411,7 @@ creat(const char *pathname_,
return rv;
}
#endif
int
creat64(const char *pathname_,
@ -416,8 +426,8 @@ creat64(const char *pathname_,
if(fd == -1)
return -1;
IOCTL_BUF real_pathname;
rv = get_underlying_filepath(fd,real_pathname);
char real_pathname[PATH_MAX];
rv = get_underlying_filepath(fd,real_pathname,sizeof(real_pathname));
if(rv == -1)
return fd;

Loading…
Cancel
Save