diff --git a/build.sh b/build.sh index 5b55964..620344d 100755 --- a/build.sh +++ b/build.sh @@ -7,11 +7,27 @@ if ! command -v apk; then exit 1 fi +# Minimize binary size +export CFLAGS="-ffunction-sections -fdata-sections -Os" + apk update -apk add alpine-sdk util-linux strace file autoconf automake libtool +apk add alpine-sdk util-linux strace file autoconf automake libtool xz + +# Build static libfuse3 with patch for https://github.com/AppImage/type2-runtime/issues/10 +apk add eudev-dev gettext-dev linux-headers meson # From https://git.alpinelinux.org/aports/tree/main/fuse3/APKBUILD +wget -c -q "https://github.com/libfuse/libfuse/releases/download/fuse-3.15.0/fuse-3.15.0.tar.xz" +tar xf fuse-3.*.tar.xz +cd fuse-3.*/ +patch -p1 < ../patches/libfuse/mount.c.diff +mkdir build +cd build +meson setup --prefix=/usr .. +meson configure --default-library static +ninja install +cd ../../ # Build static squashfuse -apk add fuse-dev fuse-static zstd-dev zstd-static zlib-dev zlib-static # fuse3-static fuse3-dev +apk add zstd-dev zstd-static zlib-dev zlib-static # fuse-dev fuse-static fuse3-static fuse3-dev wget -c -q "https://github.com/vasi/squashfuse/archive/e51978c.tar.gz" tar xf e51978c.tar.gz cd squashfuse-*/ @@ -26,11 +42,11 @@ cd - # Build static AppImage runtime export GIT_COMMIT=$(cat src/runtime/version) cd src/runtime -make runtime-fuse2 -j$(nproc) -file runtime-fuse2 -strip runtime-fuse2 -ls -lh runtime-fuse2 -echo -ne 'AI\x02' | dd of=runtime-fuse2 bs=1 count=3 seek=8 conv=notrunc # magic bytes, always do AFTER strip +make runtime-fuse3 -j$(nproc) +file runtime-fuse3 +strip runtime-fuse3 +ls -lh runtime-fuse3 +echo -ne 'AI\x02' | dd of=runtime-fuse3 bs=1 count=3 seek=8 conv=notrunc # magic bytes, always do AFTER strip cd - # Build static patchelf @@ -125,7 +141,7 @@ strip bsdtar cd - mkdir -p out -cp src/runtime/runtime-fuse2 out/runtime-fuse2-$ARCHITECTURE +cp src/runtime/runtime-fuse3 out/runtime-fuse3-$ARCHITECTURE cp patchelf-*/patchelf out/patchelf-$ARCHITECTURE cp zsync-*/zsyncmake out/zsyncmake-$ARCHITECTURE cp squashfs-tools-*/squashfs-tools/mksquashfs out/mksquashfs-$ARCHITECTURE diff --git a/chroot_build.sh b/chroot_build.sh index cf73369..ad6cfb8 100755 --- a/chroot_build.sh +++ b/chroot_build.sh @@ -18,6 +18,7 @@ cd - ############################################# sudo cp -r ./src miniroot/src +sudo cp -r ./patches miniroot/patches sudo mount -o bind /dev miniroot/dev sudo mount -t proc none miniroot/proc @@ -58,7 +59,7 @@ sudo umount miniroot/proc miniroot/sys miniroot/dev if [ "$ARCHITECTURE" = "x86" ] ; then ARCHITECTURE=i686 ; fi mkdir out/ -sudo find miniroot/ -type f -executable -name 'runtime-fuse2' -exec cp {} out/runtime-fuse2-$ARCHITECTURE \; +sudo find miniroot/ -type f -executable -name 'runtime-fuse3' -exec cp {} out/runtime-fuse3-$ARCHITECTURE \; sudo find miniroot/ -type f -executable -name 'patchelf' -exec cp {} out/patchelf-$ARCHITECTURE \; sudo find miniroot/ -type f -executable -name 'zsyncmake' -exec cp {} out/zsyncmake-$ARCHITECTURE \; sudo find miniroot/ -type f -executable -name 'mksquashfs' -exec cp {} out/mksquashfs-$ARCHITECTURE \; diff --git a/patches/libfuse/mount.c.diff b/patches/libfuse/mount.c.diff new file mode 100644 index 0000000..0dfa9cf --- /dev/null +++ b/patches/libfuse/mount.c.diff @@ -0,0 +1,130 @@ +diff --git a/lib/mount.c b/lib/mount.c +index d71e6fc55..acc1711ff 100644 +--- a/lib/mount.c ++++ b/lib/mount.c +@@ -41,7 +41,6 @@ + #define umount2(mnt, flags) unmount(mnt, (flags == 2) ? MNT_FORCE : 0) + #endif + +-#define FUSERMOUNT_PROG "fusermount3" + #define FUSE_COMMFD_ENV "_FUSE_COMMFD" + + #ifndef HAVE_FORK +@@ -117,17 +116,79 @@ static const struct fuse_opt fuse_mount_opts[] = { + FUSE_OPT_END + }; + ++int fileExists(const char* path); ++char* findBinaryInFusermountDir(const char* binaryName); ++ ++int fileExists(const char* path) { ++ FILE* file = fopen(path, "r"); ++ if (file) { ++ fclose(file); ++ return 1; ++ } ++ return 0; ++} ++ ++char* findBinaryInFusermountDir(const char* binaryName) { ++ // For security reasons, we do not search the binary on the $PATH; ++ // instead, we check if the binary exists in FUSERMOUNT_DIR ++ // as defined in meson.build ++ char* binaryPath = malloc(strlen(FUSERMOUNT_DIR) + strlen(binaryName) + 2); ++ strcpy(binaryPath, FUSERMOUNT_DIR); ++ strcat(binaryPath, "/"); ++ strcat(binaryPath, binaryName); ++ if (fileExists(binaryPath)) { ++ return binaryPath; ++ } ++ ++ // If the binary does not exist in FUSERMOUNT_DIR, return NULL ++ return NULL; ++} ++ ++static const char *fuse_mount_prog(void) ++{ ++ // Check if the FUSERMOUNT_PROG environment variable is set and if so, use it ++ const char *prog = getenv("FUSERMOUNT_PROG"); ++ if (prog) { ++ if (access(prog, X_OK) == 0) ++ return prog; ++ } ++ ++ // Check if there is a binary "fusermount3" ++ prog = findBinaryInFusermountDir("fusermount3"); ++ if (access(prog, X_OK) == 0) ++ return prog; ++ ++ // Check if there is a binary called "fusermount" ++ // This is known to work for our purposes ++ prog = findBinaryInFusermountDir("fusermount"); ++ if (access(prog, X_OK) == 0) ++ return prog; ++ ++ // For i = 4...99, check if there is a binary called "fusermount" + i ++ // It is not yet known whether this will work for our purposes, but it is better than not even attempting ++ for (int i = 4; i < 100; i++) { ++ prog = findBinaryInFusermountDir("fusermount" + i); ++ if (access(prog, X_OK) == 0) ++ return prog; ++ } ++ ++ // If all else fails, return NULL ++ return NULL; ++} ++ + static void exec_fusermount(const char *argv[]) + { +- execv(FUSERMOUNT_DIR "/" FUSERMOUNT_PROG, (char **) argv); +- execvp(FUSERMOUNT_PROG, (char **) argv); ++ const char *fusermount_prog = fuse_mount_prog(); ++ if (fusermount_prog) { ++ execv(fusermount_prog, (char **) argv); ++ } + } + + void fuse_mount_version(void) + { + int pid = fork(); + if (!pid) { +- const char *argv[] = { FUSERMOUNT_PROG, "--version", NULL }; ++ const char *argv[] = { fuse_mount_prog(), "--version", NULL }; + exec_fusermount(argv); + _exit(1); + } else if (pid != -1) +@@ -300,7 +361,7 @@ void fuse_kern_unmount(const char *mountpoint, int fd) + return; + + if(pid == 0) { +- const char *argv[] = { FUSERMOUNT_PROG, "-u", "-q", "-z", ++ const char *argv[] = { fuse_mount_prog(), "-u", "-q", "-z", + "--", mountpoint, NULL }; + + exec_fusermount(argv); +@@ -346,7 +407,7 @@ static int setup_auto_unmount(const char *mountpoint, int quiet) + } + } + +- argv[a++] = FUSERMOUNT_PROG; ++ argv[a++] = fuse_mount_prog(); + argv[a++] = "--auto-unmount"; + argv[a++] = "--"; + argv[a++] = mountpoint; +@@ -407,7 +468,7 @@ static int fuse_mount_fusermount(const char *mountpoint, struct mount_opts *mo, + } + } + +- argv[a++] = FUSERMOUNT_PROG; ++ argv[a++] = fuse_mount_prog(); + if (opts) { + argv[a++] = "-o"; + argv[a++] = opts; +@@ -421,7 +482,7 @@ static int fuse_mount_fusermount(const char *mountpoint, struct mount_opts *mo, + snprintf(env, sizeof(env), "%i", fds[0]); + setenv(FUSE_COMMFD_ENV, env, 1); + exec_fusermount(argv); +- perror("fuse: failed to exec fusermount3"); ++ perror("fuse: failed to exec fusermount"); + _exit(1); + }