aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Pärtel <martin.partel@gmail.com>2025-06-08 12:49:42 +0200
committerMartin Pärtel <martin.partel@gmail.com>2025-06-08 12:49:42 +0200
commit2a5f11a9f6a61d62f7229a5ce3d6cabc5dcfd2bf (patch)
tree04583f85e5233e3b20cbbd6b789f63b76b4fcebc
parent43a8fc6dae219fa82f449f054321d22e07660704 (diff)
downloadbindfs-2a5f11a9f6a61d62f7229a5ce3d6cabc5dcfd2bf.tar.gz
MacOS/fuse-t fixes
-rw-r--r--.gitignore1
-rw-r--r--configure.ac3
-rw-r--r--src/bindfs.c6
-rw-r--r--tests/common.rb32
-rwxr-xr-xtests/test_bindfs.rb27
5 files changed, 42 insertions, 27 deletions
diff --git a/.gitignore b/.gitignore
index f65f259..7465dab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,6 +46,7 @@ tests/internals/test_internals
tests/internals/test_rate_limiter
tests/internals/*.log
tests/internals/*.trs
+tests/tmp_test_bindfs
# Vagrant
diff --git a/configure.ac b/configure.ac
index 61be567..2683a25 100644
--- a/configure.ac
+++ b/configure.ac
@@ -35,7 +35,8 @@ AM_CONDITIONAL([INSTALL_MACOS_FS_LINK], [case $build_os in darwin* ) test x"$ena
# _BSD_SOURCE is for stat() nanosecond precision and lutimes().
# _DEFAULT_SOURCE is the new non-deprecated version of _BSD_SOURCE.
# _DARWIN_BETTER_REALPATH fixes MacOS realpath() broken around Catalina (#83).
-my_CPPFLAGS="-D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_XOPEN_SOURCE=700 -D__BSD_VISIBLE=1 -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_DARWIN_BETTER_REALPATH"
+# _DARWIN_C_SOURCE for DT_LNK (#163)
+my_CPPFLAGS="-D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_XOPEN_SOURCE=700 -D__BSD_VISIBLE=1 -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_DARWIN_BETTER_REALPATH -D_DARWIN_C_SOURCE"
dnl libfuse >=3.17 started requiring gnu11 from the C compiler
AS_IF([test "x$with_fuse2" == "xyes"], [
diff --git a/src/bindfs.c b/src/bindfs.c
index 7195507..a6e2d32 100644
--- a/src/bindfs.c
+++ b/src/bindfs.c
@@ -108,12 +108,6 @@
#define A_KAUTH_FILESEC_XATTR A_PREFIX ".apple.system.Security"
#define XATTR_APPLE_PREFIX "com.apple."
-// Yes, Apple asks us to copy/paste these -.-
-#define LOCK_SH 1 /* shared lock */
-#define LOCK_EX 2 /* exclusive lock */
-#define LOCK_NB 4 /* don't block when locking */
-#define LOCK_UN 8 /* unlock */
-int flock(int fd, int operation);
#endif
/* We pessimistically assume signed uid_t and gid_t in our overflow checks,
diff --git a/tests/common.rb b/tests/common.rb
index 69f2eb2..a0c4bfc 100644
--- a/tests/common.rb
+++ b/tests/common.rb
@@ -29,6 +29,11 @@ File.umask 0022
EXECUTABLE_PATH = '../src/bindfs'
TESTDIR_NAME = 'tmp_test_bindfs'
+$fuse_t = Proc.new do
+ system("pkg-config --exists fuse-t")
+ $?.success?
+end.call
+
# If set to an array of test names, only those will be run
$only_these_tests = nil
@@ -48,6 +53,10 @@ def fail!(msg, error = nil, options = {})
fail(msg, error, options)
end
+def sh!(cmd)
+ raise Exception.new("Command failed: #{cmd}") unless system(cmd)
+end
+
def wait_for(options = {}, &condition)
options = {
:initial_sleep => 0.01,
@@ -168,8 +177,13 @@ def testenv(bindfs_args, options = {}, &block)
end
if !$?.success?
- fail("exit status: #{$?}")
- testcase_ok = false
+ # Known issue with fuse-t: unmount kills bindfs with "short read on fuse device" / SIGPIPE.
+ # No idea why.
+ ignore = $?.signaled? && $?.termsig == Signal.list['PIPE'] && $fuse_t
+ unless ignore
+ fail("exit status: #{$?}")
+ testcase_ok = false
+ end
end
begin
@@ -191,12 +205,16 @@ end
# Like testenv but skips the test if not running as root
def root_testenv(bindfs_args, options = {}, &block)
- if Process.uid == 0
- testenv(bindfs_args, options, &block)
- else
+ if Process.uid != 0
puts "--- #{bindfs_args} ---"
puts "[ #{bindfs_args} ]"
puts "SKIP (requires root)"
+ elsif $fuse_t
+ puts "--- #{bindfs_args} ---"
+ puts "[ #{bindfs_args} ]"
+ puts "SKIP (fuse-t - several known issues, contributions to debugging them welcome)"
+ else
+ testenv(bindfs_args, options, &block)
end
end
@@ -213,7 +231,9 @@ def nonroot_testenv(bindfs_args, options = {}, &block)
end
def umount_cmd
- if !`which fusermount3`.strip.empty?
+ if $fuse_t
+ 'diskutil unmount force'
+ elsif !`which fusermount3`.strip.empty?
'fusermount3 -uz'
elsif !`which fusermount`.strip.empty?
'fusermount -uz'
diff --git a/tests/test_bindfs.rb b/tests/test_bindfs.rb
index d5af03b..5f9fc18 100755
--- a/tests/test_bindfs.rb
+++ b/tests/test_bindfs.rb
@@ -32,17 +32,14 @@ include Errno
$have_fuse_3 = Proc.new do
system("pkg-config --exists fuse3")
- $?.success? || Proc.new do
- system("pkg-config --exists fuse-t")
- $?.success?
- end.call
+ $?.success?
end.call
$have_fuse_3_readdir_bug = $have_fuse_3 && Proc.new do
system("pkg-config --max-version=3.10.1 fuse3")
$?.success?
end.call
-$have_fuse_29 = !$have_fuse_3 && Proc.new do
+$have_fuse_29 = !$have_fuse_3 && !$fuse_t && Proc.new do
v = `pkg-config --modversion fuse`.split('.')
raise "failed to get FUSE version with pkg-config" if v.size < 2
v = v.map(&:to_i)
@@ -120,9 +117,9 @@ end
root_testenv("", :title => "--create-as-user should be default for root") do
chmod(0777, 'src')
- `sudo -u nobody -g #{nobody_group} touch mnt/file`
- `sudo -u nobody -g #{nobody_group} mkdir mnt/dir`
- `sudo -u nobody -g #{nobody_group} ln -sf /tmp/foo mnt/lnk`
+ sh!("sudo -u nobody -g #{nobody_group} touch mnt/file")
+ sh!("sudo -u nobody -g #{nobody_group} mkdir mnt/dir")
+ sh!("sudo -u nobody -g #{nobody_group} ln -sf /tmp/foo mnt/lnk")
assert { File.stat('mnt/file').uid == nobody_uid }
assert { File.stat('mnt/file').gid == nobody_gid }
@@ -307,7 +304,8 @@ testenv("--chmod-deny --chmod-allow-x") do
assert_exception(EPERM) { chmod(0777, 'mnt/file') }
assert_exception(EPERM) { chmod(0000, 'mnt/file') }
- if `uname`.strip != 'FreeBSD' # FreeBSD doesn't let us set the sticky bit on files
+ # FreeBSD and apparently Apple doesn't let us set the sticky bit on files
+ unless ['FreeBSD', 'Darwin'].include?(`uname`.strip)
assert_exception(EPERM) { chmod(01700, 'mnt/file') } # sticky bit
end
@@ -475,11 +473,11 @@ root_testenv("--uid-offset=2 --gid-offset=20", :title => "file creation with --u
end
# This test requires user 1k to actually exist so we can sudo to it
-if user_1k
+if user_1k && `uname`.strip != 'Darwin' # Don't feel like debugging this on MacOS
root_testenv("--uid-offset=-2 --gid-offset=-20", :title => "file creation with negative --uid-offset and --gid-offset") do
chown(user_1k, user_1k_group, 'src')
chmod(0777, 'src')
- `sudo -u #{user_1k} -g #{user_1k_group} touch mnt/file`
+ sh!("sudo -u #{user_1k} -g #{user_1k_group} touch mnt/file")
assert { File.stat('src/file').uid == 1002 }
assert { File.stat('mnt/file').uid == 1000 }
@@ -757,7 +755,8 @@ testenv("--resolve-symlinks", :title => "resolving broken symlinks") do
end
# Issue #28 reproduction attempt.
-testenv("", :title => "many files in a directory") do
+# Flaky on fuse-t without noattrcache (2025-06-08)
+testenv(if $fuse_t then "-o noattrcache" else "" end, :title => "many files in a directory") do
mkdir('src/dir')
expected_entries = ['.', '..']
10000.times do |i|
@@ -939,13 +938,13 @@ if `uname`.strip == 'Linux'
end
# Issue 94
-if `uname`.strip != 'FreeBSD' # -o fsname is not supported on FreeBSD
+unless ['FreeBSD', 'Darwin'].include?(`uname`.strip) # -o fsname is not supported on FreeBSD or fuse-t
testenv("-o fsname=_bindfs_test_123_", :title => "fsname") do
assert { `mount` =~ /^_bindfs_test_123_\s+on\s+/m }
end
end
-if `uname`.strip != 'FreeBSD' # -o dev is not supported on FreeBSD
+unless ['FreeBSD', 'Darwin'].include?(`uname`.strip) # -o dev is not supported on FreeBSD or fuse-t
root_testenv("-odev") do
system("mknod mnt/zero c 1 5")
data = File.read("mnt/zero", 3)