aboutsummaryrefslogtreecommitdiffhomepage
path: root/cmd
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-12-27 02:25:18 +0900
committerOphestra <cat@gensokyo.uk>2025-12-27 02:30:28 +0900
commit6d3bd27220c80eb58a11b75054fbbcf67e50cc28 (patch)
tree68dd700e8988c9591cc8b703d0146292962ff07e /cmd
parenta27305cb4aa4e382b9474175139ab72bff220fd6 (diff)
cmd/sharefs: expand fuse_main
This change should not change behaviour other than making output more consistent. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'cmd')
-rw-r--r--cmd/sharefs/fuse-operations.h6
-rw-r--r--cmd/sharefs/fuse.go82
-rw-r--r--cmd/sharefs/main.go2
-rw-r--r--cmd/sharefs/test/test.py14
4 files changed, 93 insertions, 11 deletions
diff --git a/cmd/sharefs/fuse-operations.h b/cmd/sharefs/fuse-operations.h
index 9abc47ce..edcfb2a7 100644
--- a/cmd/sharefs/fuse-operations.h
+++ b/cmd/sharefs/fuse-operations.h
@@ -1,9 +1,9 @@
-#define FUSE_USE_VERSION FUSE_MAKE_VERSION(3, 4)
+#define FUSE_USE_VERSION FUSE_MAKE_VERSION(3, 12)
#include <fuse.h>
#include <fuse_lowlevel.h> /* for fuse_cmdline_help */
-#if (FUSE_VERSION < FUSE_MAKE_VERSION(3, 4))
-#error This package requires libfuse >= v3.4
+#if (FUSE_VERSION < FUSE_MAKE_VERSION(3, 12))
+#error This package requires libfuse >= v3.12
#endif
#define SHAREFS_MEDIA_RW_ID (1 << 10) - 1 /* owning gid presented to userspace */
diff --git a/cmd/sharefs/fuse.go b/cmd/sharefs/fuse.go
index 4b9764d9..8b638b75 100644
--- a/cmd/sharefs/fuse.go
+++ b/cmd/sharefs/fuse.go
@@ -25,6 +25,8 @@ import (
"strconv"
"syscall"
"unsafe"
+
+ "hakurei.app/internal/info"
)
type (
@@ -207,6 +209,8 @@ func unsafeAddArgument(args *fuseArgs, arg string) {
}
func _main(argc int, argv **C.char) int {
+ runtime.LockOSThread()
+
// don't mask creation mode, kernel already did that
syscall.Umask(0)
@@ -222,6 +226,34 @@ func _main(argc int, argv **C.char) int {
var priv C.struct_sharefs_private
pinner.Pin(&priv)
+ var opts C.struct_fuse_cmdline_opts
+ if C.fuse_parse_cmdline(&args, &opts) != 0 {
+ return 1
+ }
+ defer func() {
+ if opts.mountpoint != nil {
+ C.free(unsafe.Pointer(opts.mountpoint))
+ }
+ C.fuse_opt_free_args(&args)
+ }()
+
+ if opts.show_version != 0 {
+ fmt.Println("hakurei version", info.Version())
+ fmt.Println("FUSE library version", C.GoString(C.fuse_pkgversion()))
+ C.fuse_lowlevel_version()
+ return 0
+ }
+
+ if opts.show_help != 0 {
+ showHelp(&args)
+ return 0
+ }
+
+ if opts.show_help == 0 && opts.mountpoint == nil {
+ log.Println("no mountpoint specified")
+ return 2
+ }
+
{
source, setuid, setgid, ret := parseOpts(&args)
if ret != 0 {
@@ -247,8 +279,7 @@ func _main(argc int, argv **C.char) int {
priv.setuid, priv.setgid = C.uintptr_t(setuid), C.uintptr_t(setgid)
}
- // TODO(ophestra): spawn container here, set PR_SET_NO_NEW_PRIVS and enforce landlock
- fuse_main_return := C._fuse_main(args.argc, args.argv, &C.struct_fuse_operations{
+ op := C.struct_fuse_operations{
init: closure(C.sharefs_init),
destroy: closure(C.sharefs_destroy),
@@ -268,11 +299,52 @@ func _main(argc int, argv **C.char) int {
statfs: closure(C.sharefs_statfs),
release: closure(C.sharefs_release),
fsync: closure(C.sharefs_fsync),
- }, unsafe.Pointer(&priv))
+ }
+
+ fuse := C.fuse_new_fn(&args, &op, C.size_t(unsafe.Sizeof(op)), unsafe.Pointer(&priv))
+ if fuse == nil {
+ return 3
+ }
+ defer C.fuse_destroy(fuse)
+
+ if C.fuse_mount(fuse, opts.mountpoint) != 0 {
+ return 4
+ }
+ defer C.fuse_unmount(fuse)
+
+ // TODO(ophestra): spawn container here, set PR_SET_NO_NEW_PRIVS and enforce landlock
+ if C.fuse_daemonize(opts.foreground) != 0 {
+ return 5
+ }
+
+ se := C.fuse_get_session(fuse)
+ if C.fuse_set_signal_handlers(se) != 0 {
+ return 6
+ }
+ defer C.fuse_remove_signal_handlers(se)
+
+ if opts.singlethread != 0 {
+ if C.fuse_loop(fuse) != 0 {
+ return 8
+ }
+ } else {
+ loopConfig := C.fuse_loop_cfg_create()
+ if loopConfig == nil {
+ return 7
+ }
+ defer C.fuse_loop_cfg_destroy(loopConfig)
+
+ C.fuse_loop_cfg_set_clone_fd(loopConfig, C.uint(opts.clone_fd))
+
+ C.fuse_loop_cfg_set_idle_threads(loopConfig, opts.max_idle_threads)
+ C.fuse_loop_cfg_set_max_threads(loopConfig, opts.max_threads)
+ if C.fuse_loop_mt(fuse, loopConfig) != 0 {
+ return 8
+ }
+ }
if priv.init_failed {
return 1
- } else {
- return int(fuse_main_return)
}
+ return 0
}
diff --git a/cmd/sharefs/main.go b/cmd/sharefs/main.go
index 60924e06..c90c8624 100644
--- a/cmd/sharefs/main.go
+++ b/cmd/sharefs/main.go
@@ -4,7 +4,6 @@ import (
"log"
"os"
"path"
- "runtime"
)
// executableName is the [path.Base] name of the executable that started the current process.
@@ -19,7 +18,6 @@ var executableName = func() string {
}()
func main() {
- runtime.LockOSThread()
log.SetFlags(0)
log.SetPrefix(executableName + ": ")
diff --git a/cmd/sharefs/test/test.py b/cmd/sharefs/test/test.py
index 9b30379c..cd1d8972 100644
--- a/cmd/sharefs/test/test.py
+++ b/cmd/sharefs/test/test.py
@@ -1,6 +1,13 @@
start_all()
machine.wait_for_unit("multi-user.target")
+# To check sharefs version:
+print(machine.succeed("/etc/sharefs -V"))
+
+# Make sure sharefs did not terminate:
+machine.wait_for_unit("sharefs.service")
+
+machine.succeed("mkdir /mnt")
def check_bad_opts_output(opts, want, privileged=False):
output = machine.fail(("" if privileged else "sudo -u alice -i ") + f"/etc/sharefs -f -o source=/proc/nonexistent,{opts} /mnt 2>&1")
if output != want:
@@ -26,12 +33,17 @@ check_bad_opts_output("allow_other", "sharefs: setuid and setgid must not be 0\n
check_bad_opts_output("setuid=1023", "sharefs: setuid and setgid must not be 0\n", privileged=True)
check_bad_opts_output("setgid=1023", "sharefs: setuid and setgid must not be 0\n", privileged=True)
+# Make sure nothing actually got mounted:
+machine.fail("umount /mnt")
+machine.succeed("rmdir /mnt")
+
# Benchmark sharefs:
machine.succeed("fs_mark -v -d /sdcard/fs_mark -l /tmp/fs_log.txt")
machine.copy_from_vm("/tmp/fs_log.txt", "")
# Check permissions:
-machine.succeed("ls /var/lib/hakurei/sdcard/fs_mark")
+machine.succeed("sudo -u sharefs touch /var/lib/hakurei/sdcard/fs_mark/.check")
+machine.succeed("sudo -u sharefs rm /var/lib/hakurei/sdcard/fs_mark/.check")
machine.succeed("sudo -u alice rm -rf /sdcard/fs_mark")
machine.fail("ls /var/lib/hakurei/sdcard/fs_mark")