Author: "logesh.sekar" <logesh.sekar@timesys.com>
Date: Tue, 3 Jun 2025 18:42:54 +0530

Error:
FAILED: lib/libfuse3.so.3.17.2.p/mount.c.o 
powerpc-timesys-linux-uclibcspe-gcc -Ilib/libfuse3.so.3.17.2.p -Ilib -I../lib -Iinclude -I../include -I. -I.. -fdiagnostics-color=always -Wall -Winvalid-pch -Wextra -std=gnu11 -O2 -g -D_REENTRANT -DHAVE_LIBFUSE_PRIVATE_CONFIG_H -Wno-sign-compare -D_FILE_OFFSET_BITS=64 -Wstrict-prototypes -Wmissing-declarations -Wwrite-strings -fno-strict-aliasing -Wno-unused-result -Os -g -pipe -fPIC -pthread -DFUSE_USE_VERSION=317 '-DFUSERMOUNT_DIR="/usr/bin"' -MD -MQ lib/libfuse3.so.3.17.2.p/mount.c.o -MF lib/libfuse3.so.3.17.2.p/mount.c.o.d -o lib/libfuse3.so.3.17.2.p/mount.c.o -c ../lib/mount.c
../lib/mount.c:28:19: fatal error: spawn.h: No such file or directory #include <spawn.h>
 
Based on https: https://github.com/libfuse/libfuse/commit/bb9cecbf67341e03e53dd36b8f69520f3a26f834

uclibc doesn't support posix_spawn and provide spawn.h file, so adding fork+exec support for uclibc.

---
 lib/mount.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 173 insertions(+)

diff --git a/lib/mount.c b/lib/mount.c
index 6ed4444..9cdb8f7 100644
--- a/lib/mount.c
+++ b/lib/mount.c
@@ -25,7 +25,9 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <poll.h>
+#if !defined(__UCLIBC__)
 #include <spawn.h>
+#endif
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <sys/wait.h>
@@ -50,6 +52,12 @@
 #define FUSE_COMMFD_ENV		"_FUSE_COMMFD"
 #define FUSE_COMMFD2_ENV	"_FUSE_COMMFD2"
 
+#if defined(__UCLIBC__)
+#ifndef HAVE_FORK
+#define fork() vfork()
+#endif
+#endif
+
 #ifndef MS_DIRSYNC
 #define MS_DIRSYNC 128
 #endif
@@ -126,6 +134,24 @@ static const struct fuse_opt fuse_mount_opts[] = {
  *
  * @param out_pid might be NULL
  */
+#if defined(__UCLIBC__)
+static void exec_fusermount(const char *argv[])
+ {
+	execv(FUSERMOUNT_DIR "/" FUSERMOUNT_PROG, (char **) argv);
+	execvp(FUSERMOUNT_PROG, (char **) argv);
+}
+
+void fuse_mount_version(void)
+{
+	int pid = fork();
+	if (!pid) {
+		const char *argv[] = { FUSERMOUNT_PROG, "--version", NULL };
+		exec_fusermount(argv);
+		_exit(1);
+	} else if (pid != -1)
+		waitpid(pid, NULL, 0);
+}
+#else
 static int fusermount_posix_spawn(posix_spawn_file_actions_t *action,
 				  char const * const argv[], pid_t *out_pid)
 {
@@ -167,6 +193,7 @@ void fuse_mount_version(void)
 		fuse_log(FUSE_LOG_ERR, "Running '%s --version' failed",
 			 FUSERMOUNT_PROG);
 }
+#endif
 
 struct mount_flags {
 	const char *opt;
@@ -285,7 +312,11 @@ static int receive_fd(int fd)
 
 	while(((rv = recvmsg(fd, &msg, 0)) == -1) && errno == EINTR);
 	if (rv == -1) {
+#if defined(__UCLIBC__)
+		perror("recvmsg");
+#else
 		fuse_log(FUSE_LOG_ERR, "recvmsg failed: %s", strerror(errno));
+#endif
 		return -1;
 	}
 	if(!rv) {
@@ -336,6 +336,22 @@ void fuse_kern_unmount(const char *mountpoint, int fd)
 	if (res == 0)
 		return;
 
+#if defined(__UCLIBC__)
+	int pid;
+		pid = fork();
+	if(pid == -1)
+		return;
+
+	if(pid == 0) {
+		const char *argv[] = { FUSERMOUNT_PROG, "-u", "-q", "-z",
+				       "--", mountpoint, NULL };
+
+		exec_fusermount(argv);
+		_exit(1);
+	}
+	waitpid(pid, NULL, 0);
+}
+#else
 	char const * const argv[] =
 		{ FUSERMOUNT_PROG, "--unmount", "--quiet", "--lazy",
 				"--", mountpoint, NULL };
@@ -346,6 +395,7 @@ void fuse_kern_unmount(const char *mountpoint, int fd)
 		return;
 	}
 }
+#endif
 
 static int setup_auto_unmount(const char *mountpoint, int quiet)
 {
@@ -349,8 +349,13 @@ void fuse_kern_unmount(const char *mountpoint, int fd)
 
 static int setup_auto_unmount(const char *mountpoint, int quiet)
 {
+#if defined(__UCLIBC__)
+	int fds[2], pid;
+	int rv;
+#else
 	int fds[2];
 	pid_t pid;
+#endif
 	int res;
 
 	if (!mountpoint) {
@@ -360,6 +410,52 @@ static int setup_auto_unmount(const char *mountpoint, int quiet)
 
 	res = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
 	if(res == -1) {
+#if defined(__UCLIBC__)
+		perror("fuse: socketpair() failed");
+		return -1;
+	}
+	pid = fork();
+	if(pid == -1) {
+		perror("fuse: fork() failed");
+		close(fds[0]);
+		close(fds[1]);
+		return -1;
+	}
+	// passed to child now, so can close here.
+		if(pid == 0) {
+		char env[10];
+		const char *argv[32];
+		int a = 0;
+
+		if (quiet) {
+			int fd = open("/dev/null", O_RDONLY);
+			if (fd != -1) {
+				dup2(fd, 1);
+				dup2(fd, 2);
+			}
+		}
+
+		argv[a++] = FUSERMOUNT_PROG;
+		argv[a++] = "--auto-unmount";
+		argv[a++] = "--";
+		argv[a++] = mountpoint;
+		argv[a++] = NULL;
+
+		close(fds[1]);
+		fcntl(fds[0], F_SETFD, 0);
+		snprintf(env, sizeof(env), "%i", fds[0]);
+		setenv(FUSE_COMMFD_ENV, env, 1);
+		exec_fusermount(argv);
+		perror("fuse: failed to exec fusermount3");
+		_exit(1);
+	}
+	close(fds[0]);
+
+	// Now fusermount3 will only exit when fds[1] closes automatically when our
+	// process exits.
+	return 0;
+}
+#else
 		fuse_log(FUSE_LOG_ERR, "Setting up auto-unmountsocketpair() failed",
 			 strerror(errno));
 		return -1;
@@ -418,6 +514,82 @@ static int setup_auto_unmount(const char *mountpoint, int quiet)
 	return 0;
 	// Note: fds[1] is leakend and doesn't get FD_CLOEXEC
 }
+#endif
+
+#if defined(__UCLIBC__)
+static int fuse_mount_fusermount(const char *mountpoint, struct mount_opts *mo,
+		const char *opts, int quiet)
+{
+	int fds[2], pid;
+	int rv;
+	int res;
+
+	if (!mountpoint) {
+		fuse_log(FUSE_LOG_ERR, "fuse: missing mountpoint parameter\n");
+		return -1;
+	}
+
+	res = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
+	if(res == -1) {
+		perror("fuse: socketpair() failed");
+		return -1;
+	}
+
+	pid = fork();
+	if(pid == -1) {
+		perror("fuse: fork() failed");
+		close(fds[0]);
+		close(fds[1]);
+		return -1;
+	}
+	if(pid == 0) {
+		char env[10];
+		const char *argv[32];
+		int a = 0;
+
+		if (quiet) {
+			int fd = open("/dev/null", O_RDONLY);
+			if (fd != -1) {
+				dup2(fd, 1);
+				dup2(fd, 2);
+			}
+		}
+		argv[a++] = FUSERMOUNT_PROG;
+		if (opts) {
+			argv[a++] = "-o";
+			argv[a++] = opts;
+		}
+		argv[a++] = "--";
+		argv[a++] = mountpoint;
+		argv[a++] = NULL;
+
+
+		close(fds[1]);
+		fcntl(fds[0], F_SETFD, 0);
+		snprintf(env, sizeof(env), "%i", fds[0]);
+		setenv(FUSE_COMMFD_ENV, env, 1);
+		exec_fusermount(argv);
+		perror("fuse: failed to exec fusermount3");
+		_exit(1);
+	}
+
+	close(fds[0]);
+
+	rv = receive_fd(fds[1]);
+
+	if (!mo->auto_unmount) {
+		/* with auto_unmount option fusermount3 will not exit until
+		   this socket is closed */
+		close(fds[1]);
+		waitpid(pid, NULL, 0); /* bury zombie */
+	}
+
+	if (rv >= 0)
+		fcntl(rv, F_SETFD, FD_CLOEXEC);
+
+	return rv;
+}
+#else
 
 static int fuse_mount_fusermount(const char *mountpoint, struct mount_opts *mo,
 		const char *opts, int quiet)
@@ -497,6 +669,7 @@ static int fuse_mount_fusermount(const char *mountpoint, struct mount_opts *mo,
 
 	return fd;
 }
+#endif
 
 #ifndef O_CLOEXEC
 #define O_CLOEXEC 0

---
