vasi / squashfuse

FUSE filesystem to mount squashfs archives
Other
288 stars 66 forks source link

Support libfuse2 and libfuse3 at the same time with dlopen? #60

Closed haampie closed 3 years ago

haampie commented 3 years ago

Now that squashfuse_ll.a is a library on its own, it can be used to create self-mounting squashfs executables (e.g. appimage / xar). When distributing those, the problem is we don't know whether the target machine has libfuse2 or 3, and right now that is fixed at compile-time.

Can we use dlopen to figure this out at runtime instead?

probonopd commented 3 years ago

Now that squashfuse_ll.a is a library on its own, it can be used to create self-mounting squashfs executables (e.g. appimage / xar).

Is there an example somewhere for how to do that?

haampie commented 3 years ago

I haven't done that yet, you can use the squashfuse_ll.pc package config file to get the ll.h header & libsquashfuse_ll.{a,so} lib, and then copy the bits you need from ll_main.c to your own project.

chipturner commented 3 years ago

I would suggest finding some other FUSE filesystem that does fuse2/fuse3 at runtime. It seems like it would probably be an invasive (perhaps impossible, given data structure changes). But maybe it's possible and someone has done it. But I don't want to be first :)

haampie commented 3 years ago

Ok, that's understandable. I think I'll just happily link against a particular version of libfuse instead of dlopening anyways.

vasi commented 3 years ago

Yeah, it's probably just easier to build a static binary. Is there a reason you can't do that in your use case?

haampie commented 3 years ago

The issue is licensing; libfuse is LGPL which means

If you statically link against an LGPLed library, you must also provide your application in an object (not necessarily source) format, so that a user has the opportunity to modify the library and relink the application.

This can be problematic for users.

Edit: potentially though I could see how you could be compliant to the LGPL license without have to license your own squashfs sources in these self-mounting binaries LGPL... but IANAL.

vasi commented 3 years ago

Mmm, that makes sense. The good news is that use of fuse functions/constants is pretty isolated in squashfuse. So you could imagine just compiling ll.c twice with different headers and function-prefixes, and then your wrapper would just have to dlopen libfuse and call the right entrypoint.

I guess you'd also want to move a bunch of ll_main.c into ll.c, but honestly that seems like the right decision anyhow? @haampie does your code that uses libsquashfuse_ll end up duplicating most of ll_main.c?

haampie commented 3 years ago

That sounds like an idea indeed :)

And yes, moving things from ll_main to ll would make sense. If ll_main could just do argument parsing that'd be nice.

I've made a minimal working example here: https://github.com/haampie/appimage_runtime/ hacked together from AppImageKit's runtime.c and ll_main.c. Note that the spack commands don't work yet because PRs are pending, but installation should be reasonably easy from start to finish soon (tm).

haampie commented 3 years ago

Hm, statically linking libfuse is not a good idea because the path to the setuid binary fusermount (FUSERMOUNT_DIR) is set compile-time, so it wouldn't be portable. Shared linking is more portable.

chipturner commented 3 years ago

I am concerned all of these options add a bit of complexity for fairly niche use case. What systems only have libfuse2? libfuse3 is four years old and the last release of libfuse2 was Jan 2019.

haampie commented 3 years ago

Probably @probonopd can correct me, but appimagekit is rather conservative with dependencies (compiling against old libc etc) so that they can distribute one binary that works everywhere assuming abi compatibility. To support old systems they dlopen libfuse2, but now there are new distro's that might not have libfuse2 installed anymore, so they might need to add a hack to support both. I guess libfuse is their only dep that is breaking abi

vasi commented 3 years ago

How bad would it be to just build separate binaries, and have a small wrapper choose between them at runtime? Most Linux games do something like that.