commit:     017be872d5e1cbf058f5e08fa9255894a25736c6
Author:     Cristian Othón Martínez Vera <cfuga <AT> cfuga <DOT> mx>
AuthorDate: Tue Aug 19 04:00:50 2025 +0000
Commit:     Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Tue Aug 19 11:03:33 2025 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=017be872

sys-fs/e2fsprogs: fix compilation for version 1.47.3 with USE=fuse and musl

Patch from upstream. The current code only compiles/works with glibc

Signed-off-by: Cristian Othón Martínez Vera <cfuga <AT> cfuga.mx>
Part-of: https://github.com/gentoo/gentoo/pull/43489
Closes: https://github.com/gentoo/gentoo/pull/43489
Signed-off-by: Sam James <sam <AT> gentoo.org>

 sys-fs/e2fsprogs/e2fsprogs-1.47.3-r1.ebuild        | 170 +++++++++++++
 .../e2fsprogs-1.47.3-fix-logging-redirection.patch | 283 +++++++++++++++++++++
 2 files changed, 453 insertions(+)

diff --git a/sys-fs/e2fsprogs/e2fsprogs-1.47.3-r1.ebuild 
b/sys-fs/e2fsprogs/e2fsprogs-1.47.3-r1.ebuild
new file mode 100644
index 000000000000..fefdca03f70c
--- /dev/null
+++ b/sys-fs/e2fsprogs/e2fsprogs-1.47.3-r1.ebuild
@@ -0,0 +1,170 @@
+# Copyright 1999-2025 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=8
+
+inherit multilib-minimal systemd toolchain-funcs udev
+
+DESCRIPTION="Standard EXT2/EXT3/EXT4 filesystem utilities"
+HOMEPAGE="http://e2fsprogs.sourceforge.net/";
+SRC_URI="https://www.kernel.org/pub/linux/kernel/people/tytso/e2fsprogs/v${PV}/${P}.tar.xz";
+
+LICENSE="GPL-2 BSD"
+SLOT="0"
+KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~loong ~m68k ~mips ~ppc ~ppc64 
~riscv ~s390 ~sparc ~x86 ~amd64-linux ~x86-linux"
+IUSE="archive cron fuse nls static-libs test +tools"
+RESTRICT="!test? ( test )"
+
+RDEPEND="
+       !sys-libs/${PN}-libs
+       archive? ( app-arch/libarchive:= )
+       cron? ( sys-fs/lvm2[lvm] )
+       fuse? ( sys-fs/fuse:3= )
+       nls? ( virtual/libintl )
+       tools? ( sys-apps/util-linux )
+"
+# For testing lib/ext2fs, lib/support/libsupport.a is required, which
+# unconditionally includes '<blkid/blkid.h>' from sys-apps/util-linux.
+DEPEND="
+       ${RDEPEND}
+       test? ( sys-apps/util-linux[${MULTILIB_USEDEP}] )
+"
+BDEPEND="
+       sys-apps/texinfo
+       virtual/pkgconfig
+       nls? ( sys-devel/gettext )
+"
+
+MULTILIB_WRAPPED_HEADERS=(
+       /usr/include/ext2fs/ext2_types.h
+)
+
+PATCHES=(
+       "${FILESDIR}"/${PN}-1.42.13-fix-build-cflags.patch # bug #516854
+
+       # Upstream patches (can usually removed with next version bump)
+       "${FILESDIR}"/${PN}-1.47.3-e2scrub-order.patch
+       "${FILESDIR}"/${PN}-1.47.3-fix-logging-redirection.patch
+)
+
+src_prepare() {
+       default
+
+       cp doc/RelNotes/v${PV}.txt ChangeLog || die "Failed to copy Release 
Notes"
+
+       # Get rid of doc -- we don't use them. This also prevents a sandbox
+       # violation due to mktexfmt invocation
+       rm -r doc || die "Failed to remove doc dir"
+
+       # Prevent included intl cruft from building, bug #81096
+       sed -i -r \
+               -e 's:@LIBINTL@:@LTLIBINTL@:' \
+               MCONFIG.in || die 'intl cruft'
+}
+
+multilib_src_configure() {
+       # Keep the package from doing silly things, bug #261411
+       export VARTEXFONTS="${T}/fonts"
+
+       local myeconfargs=(
+               --with-root-prefix="${EPREFIX}"
+               $(use_with cron crond-dir "${EPREFIX}/etc/cron.d")
+               --with-systemd-unit-dir="$(systemd_get_systemunitdir)"
+               --with-udev-rules-dir="${EPREFIX}$(get_udevdir)/rules.d"
+               --enable-symlink-install
+               --enable-elf-shlibs
+               $(tc-has-tls || echo --disable-tls)
+               $(multilib_native_use_with archive libarchive direct)
+               $(multilib_native_use_enable fuse fuse2fs)
+               $(use_enable nls)
+               $(multilib_native_use_enable tools e2initrd-helper)
+               --disable-fsck
+               --disable-uuidd
+               --disable-lto
+               --with-pthread
+               --enable-largefile
+       )
+
+       # We use blkid/uuid from util-linux now
+       if use kernel_linux ; then
+               export ac_cv_lib_{uuid_uuid_generate,blkid_blkid_get_cache}=yes
+               myeconfargs+=( --disable-lib{blkid,uuid} )
+       fi
+
+       ac_cv_path_LDCONFIG=: \
+               ECONF_SOURCE="${S}" \
+               CC="$(tc-getCC)" \
+               BUILD_CC="$(tc-getBUILD_CC)" \
+               BUILD_LD="$(tc-getBUILD_LD)" \
+               econf "${myeconfargs[@]}"
+
+       if grep -qs 'USE_INCLUDED_LIBINTL.*yes' config.{log,status} ; then
+               eerror "INTL sanity check failed, aborting build."
+               eerror "Please post your ${S}/config.log file as an"
+               eerror "attachment to https://bugs.gentoo.org/81096";
+               die "Preventing included intl cruft from building"
+       fi
+}
+
+multilib_src_compile() {
+       # Parallel make issue (bug #936493)
+       emake -C lib/et V=1 compile_et
+       emake -C lib/ext2fs V=1 ext2_err.h
+
+       if multilib_is_native_abi && use tools ; then
+               emake V=1
+       else
+               emake -C lib/et V=1
+               emake -C lib/ss V=1
+               emake -C lib/ext2fs V=1
+               emake -C lib/e2p V=1
+       fi
+}
+
+multilib_src_test() {
+       if multilib_is_native_abi && use tools ; then
+               emake V=1 check
+       else
+               # Required by lib/ext2fs's check target
+               emake -C lib/support V=1
+
+               # For non-native, there's no binaries to test. Just libraries.
+               emake -C lib/et V=1 check
+               emake -C lib/ss V=1 check
+               emake -C lib/ext2fs V=1 check
+               emake -C lib/e2p V=1 check
+       fi
+}
+
+multilib_src_install() {
+       if multilib_is_native_abi && use tools ; then
+               emake STRIP=':' V=1 DESTDIR="${D}" install
+       else
+               emake -C lib/et V=1 DESTDIR="${D}" install
+               emake -C lib/ss V=1 DESTDIR="${D}" install
+               emake -C lib/ext2fs V=1 DESTDIR="${D}" install
+               emake -C lib/e2p V=1 DESTDIR="${D}" install
+       fi
+
+       # configure doesn't have an option to disable static libs
+       if ! use static-libs ; then
+               find "${ED}" -name '*.a' -delete || die
+       fi
+}
+
+multilib_src_install_all() {
+       einstalldocs
+
+       if use tools ; then
+               insinto /etc
+               doins "${FILESDIR}"/e2fsck.conf
+       fi
+}
+
+pkg_postinst() {
+       udev_reload
+}
+
+pkg_postrm() {
+       udev_reload
+}

diff --git 
a/sys-fs/e2fsprogs/files/e2fsprogs-1.47.3-fix-logging-redirection.patch 
b/sys-fs/e2fsprogs/files/e2fsprogs-1.47.3-fix-logging-redirection.patch
new file mode 100644
index 000000000000..7bd52be3dd53
--- /dev/null
+++ b/sys-fs/e2fsprogs/files/e2fsprogs-1.47.3-fix-logging-redirection.patch
@@ -0,0 +1,283 @@
+https://github.com/tytso/e2fsprogs/issues/235
+https://github.com/tytso/e2fsprogs/commit/f79abd8554e600eacc2a7c864a8332b670c9e262
+
+From: "Darrick J. Wong" <[email protected]>
+Date: Tue, 22 Jul 2025 12:40:53 -0700
+Subject: fuse2fs: fix logging redirection
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Someone pointed out that you can't just go around reassigning stdout and
+stderr because section 7.23.1 paragraph 4 of a recent C2y draft says
+that stdin, stdout, and stderr “are expressions of type "pointer to
+FILE" that point to the FILE objects associated, respectively, with the
+standard error, input, and output streams.”
+
+The use of the word "expression" should have been the warning sign that
+a symbol that can be mostly used as a pointer is not simply a pointer.
+
+Seven pages later, footnote 318 of the C2y draft clarifies that stdin,
+stdout, and stderr “need not be modifiable lvalues to which the value
+returned by the fopen function could be assigned.”
+
+"need not be" is the magic phrasing that means that glibc, musl, and
+mingw (for example) have very different declarations of stdout:
+
+glibc:
+extern FILE *stdout;           /* Standard output stream.  */
+
+musl:
+extern FILE *const stdout;
+
+mingw:
+#define stdout (&_iob[STDOUT_FILENO])
+
+All three are following the specification, yet you can write C code that
+fails to compile what otherwise looks like a normal assignment on two of
+the libraries:
+
+static FILE *const fark;       /* musl */
+
+FILE crap[3];                  /* mingw */
+#define crows (&crap[0])
+
+static FILE *stupid;           /* glibc */
+
+int main(int argc, char *argv[])
+{
+       fark = NULL;
+       crows = NULL;
+       stupid = NULL;
+}
+
+/tmp/a.c: In function ‘main’:
+/tmp/a.c:20:14: error: assignment of read-only variable ‘fark’
+   20 |         fark = NULL;
+      |              ^
+/tmp/a.c:21:15: error: lvalue required as left operand of assignment
+   21 |         crows = NULL;
+      |               ^
+
+What a useless specification!  You don't even get the same error!
+Unfortunately, this leadership vacuum means that each implementation of
+a so-called standard C library is perfectly within its right to do this.
+IOWs, the authors decided that every C programmer must divert some of
+the brainpower they could spend on their program's core algorithms to be
+really smart about this quirk.
+
+A whole committee of very smart programmers collectively decided this
+was a good way to run things decades ago so that C library authors in
+the 1980s wouldn't have to change their code, and subsequent gatherings
+have reaffirmed this "practical" decision.  Their suggestion to reassign
+stdout and stderr is to use freopen, but that walks the specified path,
+which is racy if you want both streams to point to the same file.  You
+could pass /dev/fd/XX to solve the race, but then you lose portability.
+
+In other words, they "engineered" an incomplete solution with problems
+to achieve a short term goal that nobody should care about 40 years
+later.
+
+Fix fuse2fs by rearranging the code to change STD{OUT,ERR}_FILENO to
+point to the same open logfile via dup2 and then try to use freopen on
+/dev/fd/XX to capture any stdout/err usage by the libraries that fuse2fs
+depends on.
+
+Note that we must do the whole thing over again in op_init because
+libfuse will dup2 STD{OUT,ERR}_FILE to /dev/null as part of daemonizing
+the server.
+
+Cc: [email protected] # v1.47.3
+Fixes: 5cdebf3eebc22c ("fuse2fs: stop aliasing stderr with ff->err_fp")
+Link: https://github.com/tytso/e2fsprogs/issues/235
+Signed-off-by: Darrick J. Wong <[email protected]>
+Link: https://lore.kernel.org/r/20250722194053.GO2672022@frogsfrogsfrogs
+Signed-off-by: Theodore Ts'o <[email protected]>
+--- a/misc/fuse2fs.c
++++ b/misc/fuse2fs.c
+@@ -229,6 +229,7 @@ struct fuse2fs {
+       uint8_t directio;
+       uint8_t acl;
+ 
++      int logfd;
+       int blocklog;
+       unsigned int blockmask;
+       unsigned long offset;
+@@ -792,6 +793,111 @@ static void op_destroy(void *p EXT2FS_ATTR((unused)))
+       pthread_mutex_unlock(&ff->bfl);
+ }
+ 
++/* Reopen @stream with @fileno */
++static int fuse2fs_freopen_stream(const char *path, int fileno, FILE *stream)
++{
++      char _fdpath[256];
++      const char *fdpath;
++      FILE *fp;
++      int ret;
++
++      ret = snprintf(_fdpath, sizeof(_fdpath), "/dev/fd/%d", fileno);
++      if (ret >= sizeof(_fdpath))
++              fdpath = path;
++      else
++              fdpath = _fdpath;
++
++      /*
++       * C23 defines std{out,err} as an expression of type FILE* that need
++       * not be an lvalue.  What this means is that we can't just assign to
++       * stdout: we have to use freopen, which takes a path.
++       *
++       * There's no guarantee that the OS provides a /dev/fd/X alias for open
++       * file descriptors, so if that fails, fall back to the original log
++       * file path.  We'd rather not do a path-based reopen because that
++       * exposes us to rename race attacks.
++       */
++      fp = freopen(fdpath, "a", stream);
++      if (!fp && errno == ENOENT && fdpath == _fdpath)
++              fp = freopen(path, "a", stream);
++      if (!fp) {
++              perror(fdpath);
++              return -1;
++      }
++
++      return 0;
++}
++
++/* Redirect stdout/stderr to a file, or return a mount-compatible error. */
++static int fuse2fs_capture_output(struct fuse2fs *ff, const char *path)
++{
++      int ret;
++      int fd;
++
++      /*
++       * First, open the log file path with system calls so that we can
++       * redirect the stdout/stderr file numbers (typically 1 and 2) to our
++       * logfile descriptor.  We'd like to avoid allocating extra file
++       * objects in the kernel if we can because pos will be the same between
++       * stdout and stderr.
++       */
++      if (ff->logfd < 0) {
++              fd = open(path, O_WRONLY | O_CREAT | O_APPEND, 0600);
++              if (fd < 0) {
++                      perror(path);
++                      return -1;
++              }
++
++              /*
++               * Save the newly opened fd in case we have to do this again in
++               * op_init.
++               */
++              ff->logfd = fd;
++      }
++
++      ret = dup2(ff->logfd, STDOUT_FILENO);
++      if (ret < 0) {
++              perror(path);
++              return -1;
++      }
++
++      ret = dup2(ff->logfd, STDERR_FILENO);
++      if (ret < 0) {
++              perror(path);
++              return -1;
++      }
++
++      /*
++       * Now that we've changed STD{OUT,ERR}_FILENO to be the log file, use
++       * freopen to make sure that std{out,err} (the C library abstractions)
++       * point to the STDXXX_FILENO because any of our library dependencies
++       * might decide to printf to one of those streams and we want to
++       * capture all output in the log.
++       */
++      ret = fuse2fs_freopen_stream(path, STDOUT_FILENO, stdout);
++      if (ret)
++              return ret;
++      ret = fuse2fs_freopen_stream(path, STDERR_FILENO, stderr);
++      if (ret)
++              return ret;
++
++      return 0;
++}
++
++/* Set up debug and error logging files */
++static int fuse2fs_setup_logging(struct fuse2fs *ff)
++{
++      char *logfile = getenv("FUSE2FS_LOGFILE");
++      if (logfile)
++              return fuse2fs_capture_output(ff, logfile);
++
++      /* in kernel mode, try to log errors to the kernel log */
++      if (ff->kernel)
++              fuse2fs_capture_output(ff, "/dev/ttyprintk");
++
++      return 0;
++}
++
+ static void *op_init(struct fuse_conn_info *conn
+ #if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+                       , struct fuse_config *cfg EXT2FS_ATTR((unused))
+@@ -807,6 +913,17 @@ static void *op_init(struct fuse_conn_info *conn
+               translate_error(global_fs, 0, EXT2_ET_BAD_MAGIC);
+               return NULL;
+       }
++
++      /*
++       * Configure logging a second time, because libfuse might have
++       * redirected std{out,err} as part of daemonization.  If this fails,
++       * give up and move on.
++       */
++      fuse2fs_setup_logging(ff);
++      if (ff->logfd >= 0)
++              close(ff->logfd);
++      ff->logfd = -1;
++
+       fs = ff->fs;
+       dbg_printf(ff, "%s: dev=%s\n", __func__, fs->device_name);
+ #ifdef FUSE_CAP_IOCTL_DIR
+@@ -4448,7 +4565,6 @@ int main(int argc, char *argv[])
+       struct fuse2fs fctx;
+       errcode_t err;
+       FILE *orig_stderr = stderr;
+-      char *logfile;
+       char extra_args[BUFSIZ];
+       int ret;
+       int flags = EXT2_FLAG_64BITS | EXT2_FLAG_THREADS | EXT2_FLAG_EXCLUSIVE |
+@@ -4456,6 +4572,7 @@ int main(int argc, char *argv[])
+ 
+       memset(&fctx, 0, sizeof(fctx));
+       fctx.magic = FUSE2FS_MAGIC;
++      fctx.logfd = -1;
+ 
+       ret = fuse_opt_parse(&args, &fctx, fuse2fs_opts, fuse2fs_opt_proc);
+       if (ret)
+@@ -4482,23 +4599,11 @@ int main(int argc, char *argv[])
+ #endif
+       add_error_table(&et_ext2_error_table);
+ 
+-      /* Set up error logging */
+-      logfile = getenv("FUSE2FS_LOGFILE");
+-      if (logfile) {
+-              FILE *fp = fopen(logfile, "a");
+-              if (!fp) {
+-                      perror(logfile);
+-                      goto out;
+-              }
+-              stderr = fp;
+-              stdout = fp;
+-      } else if (fctx.kernel) {
+-              /* in kernel mode, try to log errors to the kernel log */
+-              FILE *fp = fopen("/dev/ttyprintk", "a");
+-              if (fp) {
+-                      stderr = fp;
+-                      stdout = fp;
+-              }
++      ret = fuse2fs_setup_logging(&fctx);
++      if (ret) {
++              /* operational error */
++              ret = 2;
++              goto out;
+       }
+ 
+       /* Will we allow users to allocate every last block? */
+-- 
+cgit 1.2.3-korg
+

Reply via email to