In GNU libffcall, I need to use the function hasmntopt(). Since it does not
exist on Android API levels <= 25, I'm adding a gnulib module for it.

The unit tests of this module reveal that the implementation of hasmntopt()
is broken on musl libc: it confuses the "atime" option with the "noatime"
option; but these options have opposite meanings.

These patches provide the module, with the necessary override.


2024-08-19  Bruno Haible  <br...@clisp.org>

        hasmntopt: Add tests.
        * tests/test-hasmntopt.c: New file.
        * modules/hasmntopt-tests: New file.

        hasmntopt: New module.
        * lib/mntent.in.h: Add config.h check.
        (hasmntopt): New declaration.
        * lib/hasmntopt.c: New file, based on glibc/misc/mntent_r.c.
        * m4/hasmntopt.m4: New file.
        * m4/mntent_h.m4 (gl_MNTENT_H): Test whether hasmntopt is declared.
        (gl_MNTENT_H_REQUIRE_DEFAULTS): Initialize GNULIB_HASMNTOPT.
        (gl_MNTENT_H_DEFAULTS): Initialize HAVE_HASMNTOPT, HAVE_SETMNTENT,
        REPLACE_HASMNTOPT.
        * modules/mntent (Depends-on): Add snippet/arg-nonnull, snippet/c++defs,
        snippet/warn-on-use.
        (Makefile.am): Insert c++defs.h, arg-nonnull.h, warn-on-use.h into
        mntent.h. Substitute GNULIB_HASMNTOPT, HAVE_HASMNTOPT, HAVE_SETMNTENT,
        REPLACE_HASMNTOPT.
        * modules/hasmntopt: New file.
        * doc/glibc-functions/hasmntopt.texi: Mention the new module and the
        musl bug.
        * doc/glibc-functions/setmntent.texi: Update info about Android.
        * doc/glibc-functions/getmntent_r.texi: Likewise.
        * doc/glibc-functions/endmntent.texi: Likewise.

2024-08-19  Bruno Haible  <br...@clisp.org>

        mntent: New module.
        * lib/mntent.in.h: New file.
        * m4/mntent_h.m4: New file.
        * modules/mntent: New file.
        * doc/glibc-headers/mntent.texi: Mention the new module.
        * top/maint.mk (gl_prefer_angle_bracket_headers_): Add mntent.h.
        * doc/gnulib-tool.texi (Style of #include statements): Add mntent.h to
        the list.

>From 662fd337dbb0b85b7ff69a9a12e5b43bad063c57 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Mon, 19 Aug 2024 13:46:02 +0200
Subject: [PATCH 1/3] mntent: New module.

* lib/mntent.in.h: New file.
* m4/mntent_h.m4: New file.
* modules/mntent: New file.
* doc/glibc-headers/mntent.texi: Mention the new module.
* top/maint.mk (gl_prefer_angle_bracket_headers_): Add mntent.h.
* doc/gnulib-tool.texi (Style of #include statements): Add mntent.h to
the list.
---
 ChangeLog                     | 11 ++++++++
 doc/glibc-headers/mntent.texi |  2 +-
 doc/gnulib-tool.texi          |  1 +
 lib/mntent.in.h               | 41 +++++++++++++++++++++++++++
 m4/mntent_h.m4                | 52 +++++++++++++++++++++++++++++++++++
 modules/mntent                | 47 +++++++++++++++++++++++++++++++
 top/maint.mk                  |  1 +
 7 files changed, 154 insertions(+), 1 deletion(-)
 create mode 100644 lib/mntent.in.h
 create mode 100644 m4/mntent_h.m4
 create mode 100644 modules/mntent

diff --git a/ChangeLog b/ChangeLog
index 7486fb8047..390733f163 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2024-08-19  Bruno Haible  <br...@clisp.org>
+
+	mntent: New module.
+	* lib/mntent.in.h: New file.
+	* m4/mntent_h.m4: New file.
+	* modules/mntent: New file.
+	* doc/glibc-headers/mntent.texi: Mention the new module.
+	* top/maint.mk (gl_prefer_angle_bracket_headers_): Add mntent.h.
+	* doc/gnulib-tool.texi (Style of #include statements): Add mntent.h to
+	the list.
+
 2024-08-17  Bruno Haible  <br...@clisp.org>
 
 	once: Fix pthread-rwlock crashes with clang (regr. 2024-08-07).
diff --git a/doc/glibc-headers/mntent.texi b/doc/glibc-headers/mntent.texi
index cbaf805453..b6fc955fc8 100644
--- a/doc/glibc-headers/mntent.texi
+++ b/doc/glibc-headers/mntent.texi
@@ -19,7 +19,7 @@
 @uref{https://www.kernel.org/doc/man-pages/online/pages/man3/setmntent.3.html,,man setmntent}.
 @end itemize
 
-Gnulib module: ---
+Gnulib module: mntent
 
 Portability problems fixed by Gnulib:
 @itemize
diff --git a/doc/gnulib-tool.texi b/doc/gnulib-tool.texi
index e26380cd24..41eccb3019 100644
--- a/doc/gnulib-tool.texi
+++ b/doc/gnulib-tool.texi
@@ -625,6 +625,7 @@
 @item @code{error.h}
 @item @code{getopt.h}
 @item @code{malloc.h}
+@item @code{mntent.h}
 @item @code{omp.h}
 @item @code{pty.h}
 @item @code{selinux/selinux.h}
diff --git a/lib/mntent.in.h b/lib/mntent.in.h
new file mode 100644
index 0000000000..4da9d85314
--- /dev/null
+++ b/lib/mntent.in.h
@@ -0,0 +1,41 @@
+/* Provide a more complete mntent.h.
+
+   Copyright (C) 2024 Free Software Foundation, Inc.
+
+   This file is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   This file is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+#if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+#endif
+@PRAGMA_COLUMNS@
+
+#ifndef _@GUARD_PREFIX@_MNTENT_H
+
+/* The include_next requires a split double-inclusion guard.  */
+#@INCLUDE_NEXT@ @NEXT_MNTENT_H@
+
+#ifndef _@GUARD_PREFIX@_MNTENT_H
+#define _@GUARD_PREFIX@_MNTENT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _@GUARD_PREFIX@_MNTENT_H */
+#endif /* _@GUARD_PREFIX@_MNTENT_H */
diff --git a/m4/mntent_h.m4 b/m4/mntent_h.m4
new file mode 100644
index 0000000000..f067cd0293
--- /dev/null
+++ b/m4/mntent_h.m4
@@ -0,0 +1,52 @@
+# mntent_h.m4
+# serial 1
+dnl Copyright (C) 2024 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN_ONCE([gl_MNTENT_H],
+[
+  dnl Ensure to expand the default settings once only, before all statements
+  dnl that occur in other macros.
+  AC_REQUIRE([gl_MNTENT_H_DEFAULTS])
+
+  AC_CHECK_HEADERS_ONCE([mntent.h])
+  dnl For now, we provide a <mntent.h> wrapper only if the system already has
+  dnl a <mntent.h>.
+  if test $ac_cv_header_mntent_h = yes; then
+    GL_GENERATE_MNTENT_H=true
+    gl_CHECK_NEXT_HEADERS([mntent.h])
+  else
+    GL_GENERATE_MNTENT_H=false
+  fi
+])
+
+# gl_MNTENT_MODULE_INDICATOR([modulename])
+# sets the shell variable that indicates the presence of the given module
+# to a C preprocessor expression that will evaluate to 1.
+# This macro invocation must not occur in macros that are AC_REQUIREd.
+AC_DEFUN([gl_MNTENT_MODULE_INDICATOR],
+[
+  dnl Ensure to expand the default settings once only.
+  gl_MNTENT_H_REQUIRE_DEFAULTS
+  gl_MODULE_INDICATOR_SET_VARIABLE([$1])
+  dnl Define it also as a C macro, for the benefit of the unit tests.
+  gl_MODULE_INDICATOR_FOR_TESTS([$1])
+])
+
+# Initializes the default values for AC_SUBSTed shell variables.
+# This macro must not be AC_REQUIREd.  It must only be invoked, and only
+# outside of macros or in macros that are not AC_REQUIREd.
+AC_DEFUN([gl_MNTENT_H_REQUIRE_DEFAULTS],
+[
+  m4_defun(GL_MODULE_INDICATOR_PREFIX[_MNTENT_H_MODULE_INDICATOR_DEFAULTS], [
+  ])
+  m4_require(GL_MODULE_INDICATOR_PREFIX[_MNTENT_H_MODULE_INDICATOR_DEFAULTS])
+  AC_REQUIRE([gl_MNTENT_H_DEFAULTS])
+])
+
+AC_DEFUN([gl_MNTENT_H_DEFAULTS],
+[
+  dnl Assume proper GNU behavior unless another module says otherwise.
+])
diff --git a/modules/mntent b/modules/mntent
new file mode 100644
index 0000000000..eb30116fad
--- /dev/null
+++ b/modules/mntent
@@ -0,0 +1,47 @@
+Description:
+<mntent.h> with more declarations.
+
+Files:
+lib/mntent.in.h
+m4/mntent_h.m4
+
+Depends-on:
+gen-header
+include_next
+
+configure.ac:
+gl_MNTENT_H
+gl_CONDITIONAL_HEADER([mntent.h])
+AC_PROG_MKDIR_P
+
+Makefile.am:
+BUILT_SOURCES += $(MNTENT_H)
+
+# We need the following in order to create <mntent.h> when desired.
+if GL_GENERATE_MNTENT_H
+mntent.h: mntent.in.h $(top_builddir)/config.status
+	$(AM_V_GEN)$(MKDIR_P) '%reldir%'
+	$(AM_V_at)$(SED_HEADER_STDOUT) \
+	      -e 's|@''GUARD_PREFIX''@|${gl_include_guard_prefix}|g' \
+	      -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+	      -e 's|@''NEXT_MNTENT_H''@|$(NEXT_MNTENT_H)|g' \
+	      $(srcdir)/mntent.in.h > $@-t
+	$(AM_V_at)mv $@-t $@
+else
+mntent.h: $(top_builddir)/config.status
+	rm -f $@
+endif
+MOSTLYCLEANFILES += mntent.h mntent.h-t
+
+Include:
+#if HAVE_MNTENT_H
+<mntent.h>
+#endif
+
+License:
+LGPLv2+
+
+Maintainer:
+all
diff --git a/top/maint.mk b/top/maint.mk
index 37f6889b06..39372f99f4 100644
--- a/top/maint.mk
+++ b/top/maint.mk
@@ -565,6 +565,7 @@ gl_prefer_angle_bracket_headers_ ?= \
   locale.h		\
   malloc.h		\
   math.h		\
+  mntent.h		\
   monetary.h		\
   net/if.h		\
   netdb.h		\
-- 
2.34.1

>From b1c67ccfeab56c6d2f452f03f01cdb5cbaedb8b6 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Mon, 19 Aug 2024 16:20:08 +0200
Subject: [PATCH 2/3] hasmntopt: New module.

* lib/mntent.in.h: Add config.h check.
(hasmntopt): New declaration.
* lib/hasmntopt.c: New file, based on glibc/misc/mntent_r.c.
* m4/hasmntopt.m4: New file.
* m4/mntent_h.m4 (gl_MNTENT_H): Test whether hasmntopt is declared.
(gl_MNTENT_H_REQUIRE_DEFAULTS): Initialize GNULIB_HASMNTOPT.
(gl_MNTENT_H_DEFAULTS): Initialize HAVE_HASMNTOPT, HAVE_SETMNTENT,
REPLACE_HASMNTOPT.
* modules/mntent (Depends-on): Add snippet/arg-nonnull, snippet/c++defs,
snippet/warn-on-use.
(Makefile.am): Insert c++defs.h, arg-nonnull.h, warn-on-use.h into
mntent.h. Substitute GNULIB_HASMNTOPT, HAVE_HASMNTOPT, HAVE_SETMNTENT,
REPLACE_HASMNTOPT.
* modules/hasmntopt: New file.
* doc/glibc-functions/hasmntopt.texi: Mention the new module and the
musl bug.
* doc/glibc-functions/setmntent.texi: Update info about Android.
* doc/glibc-functions/getmntent_r.texi: Likewise.
* doc/glibc-functions/endmntent.texi: Likewise.
---
 ChangeLog                            | 23 +++++++++
 doc/glibc-functions/endmntent.texi   |  2 +-
 doc/glibc-functions/getmntent_r.texi |  2 +-
 doc/glibc-functions/hasmntopt.texi   | 11 +++-
 doc/glibc-functions/setmntent.texi   |  2 +-
 lib/hasmntopt.c                      | 44 ++++++++++++++++
 lib/mntent.in.h                      | 45 +++++++++++++++++
 m4/hasmntopt.m4                      | 75 ++++++++++++++++++++++++++++
 m4/mntent_h.m4                       | 12 ++++-
 modules/hasmntopt                    | 32 ++++++++++++
 modules/mntent                       | 12 ++++-
 11 files changed, 253 insertions(+), 7 deletions(-)
 create mode 100644 lib/hasmntopt.c
 create mode 100644 m4/hasmntopt.m4
 create mode 100644 modules/hasmntopt

diff --git a/ChangeLog b/ChangeLog
index 390733f163..8cbd4b8a80 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2024-08-19  Bruno Haible  <br...@clisp.org>
+
+	hasmntopt: New module.
+	* lib/mntent.in.h: Add config.h check.
+	(hasmntopt): New declaration.
+	* lib/hasmntopt.c: New file, based on glibc/misc/mntent_r.c.
+	* m4/hasmntopt.m4: New file.
+	* m4/mntent_h.m4 (gl_MNTENT_H): Test whether hasmntopt is declared.
+	(gl_MNTENT_H_REQUIRE_DEFAULTS): Initialize GNULIB_HASMNTOPT.
+	(gl_MNTENT_H_DEFAULTS): Initialize HAVE_HASMNTOPT, HAVE_SETMNTENT,
+	REPLACE_HASMNTOPT.
+	* modules/mntent (Depends-on): Add snippet/arg-nonnull, snippet/c++defs,
+	snippet/warn-on-use.
+	(Makefile.am): Insert c++defs.h, arg-nonnull.h, warn-on-use.h into
+	mntent.h. Substitute GNULIB_HASMNTOPT, HAVE_HASMNTOPT, HAVE_SETMNTENT,
+	REPLACE_HASMNTOPT.
+	* modules/hasmntopt: New file.
+	* doc/glibc-functions/hasmntopt.texi: Mention the new module and the
+	musl bug.
+	* doc/glibc-functions/setmntent.texi: Update info about Android.
+	* doc/glibc-functions/getmntent_r.texi: Likewise.
+	* doc/glibc-functions/endmntent.texi: Likewise.
+
 2024-08-19  Bruno Haible  <br...@clisp.org>
 
 	mntent: New module.
diff --git a/doc/glibc-functions/endmntent.texi b/doc/glibc-functions/endmntent.texi
index 501083ca9b..b887e0ee67 100644
--- a/doc/glibc-functions/endmntent.texi
+++ b/doc/glibc-functions/endmntent.texi
@@ -25,5 +25,5 @@
 @itemize
 @item
 This function is missing on some platforms:
-macOS 14, FreeBSD 14.0, NetBSD 10.0, OpenBSD 7.5, Minix 3.1.8, Solaris 11.4, mingw, MSVC 14, Android 4.4.
+macOS 14, FreeBSD 14.0, NetBSD 10.0, OpenBSD 7.5, Minix 3.1.8, Solaris 11.4, mingw, MSVC 14, Android API level 20.
 @end itemize
diff --git a/doc/glibc-functions/getmntent_r.texi b/doc/glibc-functions/getmntent_r.texi
index bbd2ee97f4..12629a13a8 100644
--- a/doc/glibc-functions/getmntent_r.texi
+++ b/doc/glibc-functions/getmntent_r.texi
@@ -25,5 +25,5 @@
 @itemize
 @item
 This function is missing on many non-glibc platforms:
-macOS 14, FreeBSD 14.0, NetBSD 10.0, OpenBSD 7.5, Minix 3.1.8, AIX 5.1, HP-UX 11, Solaris 11.4, Cygwin 1.7.x, mingw, MSVC 14, Android 4.4.
+macOS 14, FreeBSD 14.0, NetBSD 10.0, OpenBSD 7.5, Minix 3.1.8, AIX 5.1, HP-UX 11, Solaris 11.4, Cygwin 1.7.x, mingw, MSVC 14, Android API level 20.
 @end itemize
diff --git a/doc/glibc-functions/hasmntopt.texi b/doc/glibc-functions/hasmntopt.texi
index a4784c6eb6..ebc92fe6c8 100644
--- a/doc/glibc-functions/hasmntopt.texi
+++ b/doc/glibc-functions/hasmntopt.texi
@@ -15,15 +15,22 @@
 @uref{https://www.kernel.org/doc/man-pages/online/pages/man3/hasmntopt.3.html,,man hasmntopt}.
 @end itemize
 
-Gnulib module: ---
+Gnulib module: hasmntopt
 
 Portability problems fixed by Gnulib:
 @itemize
+@item
+This function is missing on some platforms:
+Cygwin 3.5.3, Android API level 25.
+@item
+This function returns wrong results on some platforms:
+@c https://www.openwall.com/lists/musl/2024/08/19/1
+musl libc 1.2.5.
 @end itemize
 
 Portability problems not fixed by Gnulib:
 @itemize
 @item
 This function is missing on some platforms:
-macOS 14, FreeBSD 14.0, NetBSD 10.0, OpenBSD 7.5, Minix 3.1.8, Cygwin 2.9, mingw, MSVC 14, Android 7.1.
+macOS 14, FreeBSD 14.0, NetBSD 10.0, OpenBSD 7.5, Minix 3.1.8, mingw, MSVC 14.
 @end itemize
diff --git a/doc/glibc-functions/setmntent.texi b/doc/glibc-functions/setmntent.texi
index 291b71492c..930c432e8f 100644
--- a/doc/glibc-functions/setmntent.texi
+++ b/doc/glibc-functions/setmntent.texi
@@ -25,5 +25,5 @@
 @itemize
 @item
 This function is missing on some platforms:
-macOS 14, FreeBSD 14.0, NetBSD 10.0, OpenBSD 7.5, Minix 3.1.8, Solaris 11.4, mingw, MSVC 14, Android 4.4.
+macOS 14, FreeBSD 14.0, NetBSD 10.0, OpenBSD 7.5, Minix 3.1.8, Solaris 11.4, mingw, MSVC 14, Android API level 20.
 @end itemize
diff --git a/lib/hasmntopt.c b/lib/hasmntopt.c
new file mode 100644
index 0000000000..15c7e824f0
--- /dev/null
+++ b/lib/hasmntopt.c
@@ -0,0 +1,44 @@
+/* hasmntopt() function: test for the presence of a mount option.
+
+   Copyright (C) 1995-2024 Free Software Foundation, Inc.
+
+   This file is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   This file is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <mntent.h>
+
+#include <string.h>
+
+char *
+hasmntopt (const struct mntent *mnt, const char *opt)
+{
+  const size_t optlen = strlen (opt);
+  char *rest = mnt->mnt_opts, *p;
+
+  while ((p = strstr (rest, opt)) != NULL)
+    {
+      if ((p == rest || p[-1] == ',')
+          && (p[optlen] == '\0' || p[optlen] == '=' || p[optlen] == ','))
+        return p;
+
+      rest = strchr (p, ',');
+      if (rest == NULL)
+        break;
+      ++rest;
+    }
+
+  return NULL;
+}
diff --git a/lib/mntent.in.h b/lib/mntent.in.h
index 4da9d85314..c8750fec66 100644
--- a/lib/mntent.in.h
+++ b/lib/mntent.in.h
@@ -28,11 +28,56 @@
 #ifndef _@GUARD_PREFIX@_MNTENT_H
 #define _@GUARD_PREFIX@_MNTENT_H
 
+/* This file uses GNULIB_POSIXCHECK, HAVE_RAW_DECL_*.  */
+#if !_GL_CONFIG_H_INCLUDED
+ #error "Please include config.h first."
+#endif
+
+/* The definitions of _GL_FUNCDECL_RPL etc. are copied here.  */
+
+/* The definition of _GL_ARG_NONNULL is copied here.  */
+
+/* The definition of _GL_WARN_ON_USE is copied here.  */
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 
+#if @GNULIB_HASMNTOPT@ && @HAVE_SETMNTENT@
+/* Searches ME->mnt_opts for an option matching OPTION.
+   Returns the address of the substring, or null if none found.  */
+# if @REPLACE_HASMNTOPT@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef hasmntopt
+#   define hasmntopt rpl_hasmntopt
+#  endif
+_GL_FUNCDECL_RPL (hasmntopt, char *,
+                  (const struct mntent *me, const char *option),
+                  _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_RPL (hasmntopt, char *,
+                  (const struct mntent *me, const char *option));
+# else
+#  if !@HAVE_HASMNTOPT@
+_GL_FUNCDECL_SYS (hasmntopt, char *,
+                  (const struct mntent *me, const char *option),
+                  _GL_ARG_NONNULL ((1, 2)));
+#  endif
+_GL_CXXALIAS_SYS (hasmntopt, char *,
+                  (const struct mntent *me, const char *option));
+# endif
+# if __GLIBC__ >= 2
+_GL_CXXALIASWARN (hasmntopt);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef hasmntopt
+# if HAVE_RAW_DECL_HASMNTOPT
+_GL_WARN_ON_USE (hasmntopt, "hasmntopt is unportable - "
+                 "use gnulib module hasmntopt for portability");
+# endif
+#endif
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/m4/hasmntopt.m4 b/m4/hasmntopt.m4
new file mode 100644
index 0000000000..2dcaa7db56
--- /dev/null
+++ b/m4/hasmntopt.m4
@@ -0,0 +1,75 @@
+# hasmntopt.m4
+# serial 1
+dnl Copyright (C) 2024 Free Software Foundation, Inc.
+dnl
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_HASMNTOPT],
+[
+  AC_REQUIRE([gl_MNTENT_H_DEFAULTS])
+  AC_REQUIRE([AC_CANONICAL_HOST])
+
+  gl_CHECK_FUNCS_ANDROID([setmntent],
+    [[#include <stdio.h>
+      #include <mntent.h>
+    ]])
+  if test $ac_cv_func_setmntent != yes; then
+    HAVE_SETMNTENT=0
+  fi
+
+  gl_CHECK_FUNCS_ANDROID([hasmntopt],
+    [[#include <stdio.h>
+      #include <mntent.h>
+    ]])
+  if test $ac_cv_func_hasmntopt = yes; then
+    dnl hasmntopt has the dumbest possible implementation on musl libc 1.2.5:
+    dnl it confuses the "atime" option with the "noatime" option.
+    AC_CACHE_CHECK([whether hasmntopt works],
+      [gl_cv_func_hasmntopt_works],
+      [AC_RUN_IFELSE(
+         [AC_LANG_PROGRAM(
+            [[#include <mntent.h>
+              #include <stddef.h>
+            ]],
+            [[int result = 0;
+              /* This test fails on musl libc 1.2.5.  */
+              {
+                char options[] = "rw,noatime";
+                struct mntent me;
+                me.mnt_opts = options;
+                if (hasmntopt (&me, "atime") != NULL)
+                  result |= 1;
+              }
+              return result;
+            ]])
+         ],
+         [gl_cv_func_hasmntopt_works=yes],
+         [gl_cv_func_hasmntopt_works=no],
+         [case "$host_os" in
+                                # Guess yes on glibc systems.
+            *-gnu* | gnu*)      gl_cv_func_hasmntopt_works="guessing yes" ;;
+                                # Guess no on musl systems.
+            *-musl* | midipix*) gl_cv_func_hasmntopt_works="guessing no" ;;
+            *)                  gl_cv_func_hasmntopt_works="$gl_cross_guess_normal" ;;
+          esac
+         ])
+    ])
+    case "$gl_cv_func_hasmntopt_works" in
+      *yes) ;;
+      *)    REPLACE_HASMNTOPT=1 ;;
+    esac
+  else
+    HAVE_HASMNTOPT=0
+    case "$gl_cv_onwards_func_hasmntopt" in
+      future*) REPLACE_HASMNTOPT=1 ;;
+    esac
+  fi
+])
+
+# Prerequisites of lib/hasmntopt.c.
+AC_DEFUN([gl_PREREQ_HASMNTOPT],
+[
+  :
+])
diff --git a/m4/mntent_h.m4 b/m4/mntent_h.m4
index f067cd0293..30eaee90c2 100644
--- a/m4/mntent_h.m4
+++ b/m4/mntent_h.m4
@@ -1,5 +1,5 @@
 # mntent_h.m4
-# serial 1
+# serial 2
 dnl Copyright (C) 2024 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -20,6 +20,12 @@ AC_DEFUN_ONCE([gl_MNTENT_H]
   else
     GL_GENERATE_MNTENT_H=false
   fi
+
+  dnl Check for declarations of anything we want to poison if the
+  dnl corresponding gnulib module is not in use.
+  gl_WARN_ON_USE_PREPARE([[#include <mntent.h>
+    ]],
+    [hasmntopt])
 ])
 
 # gl_MNTENT_MODULE_INDICATOR([modulename])
@@ -41,6 +47,7 @@ AC_DEFUN([gl_MNTENT_MODULE_INDICATOR]
 AC_DEFUN([gl_MNTENT_H_REQUIRE_DEFAULTS],
 [
   m4_defun(GL_MODULE_INDICATOR_PREFIX[_MNTENT_H_MODULE_INDICATOR_DEFAULTS], [
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_HASMNTOPT])
   ])
   m4_require(GL_MODULE_INDICATOR_PREFIX[_MNTENT_H_MODULE_INDICATOR_DEFAULTS])
   AC_REQUIRE([gl_MNTENT_H_DEFAULTS])
@@ -49,4 +56,7 @@ AC_DEFUN([gl_MNTENT_H_REQUIRE_DEFAULTS]
 AC_DEFUN([gl_MNTENT_H_DEFAULTS],
 [
   dnl Assume proper GNU behavior unless another module says otherwise.
+  HAVE_HASMNTOPT=1;      AC_SUBST([HAVE_HASMNTOPT])
+  HAVE_SETMNTENT=1;      AC_SUBST([HAVE_SETMNTENT])
+  REPLACE_HASMNTOPT=0;   AC_SUBST([REPLACE_HASMNTOPT])
 ])
diff --git a/modules/hasmntopt b/modules/hasmntopt
new file mode 100644
index 0000000000..6fdd897f0b
--- /dev/null
+++ b/modules/hasmntopt
@@ -0,0 +1,32 @@
+Description:
+hasmntopt() function: test for the presence of a mount option.
+
+Files:
+lib/hasmntopt.c
+m4/hasmntopt.m4
+
+Depends-on:
+mntent
+
+configure.ac:
+gl_FUNC_HASMNTOPT
+gl_CONDITIONAL([GL_COND_OBJ_HASMNTOPT],
+               [test $HAVE_SETMNTENT = 1 && { test $HAVE_HASMNTOPT = 0 || test $REPLACE_HASMNTOPT = 1; }])
+AM_COND_IF([GL_COND_OBJ_HASMNTOPT], [
+  gl_PREREQ_HASMNTOPT
+])
+gl_MNTENT_MODULE_INDICATOR([hasmntopt])
+
+Makefile.am:
+if GL_COND_OBJ_HASMNTOPT
+lib_SOURCES += hasmntopt.c
+endif
+
+Include:
+<mntent.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+glibc
diff --git a/modules/mntent b/modules/mntent
index eb30116fad..8dc48c38d0 100644
--- a/modules/mntent
+++ b/modules/mntent
@@ -8,6 +8,9 @@ m4/mntent_h.m4
 Depends-on:
 gen-header
 include_next
+snippet/arg-nonnull
+snippet/c++defs
+snippet/warn-on-use
 
 configure.ac:
 gl_MNTENT_H
@@ -19,7 +22,7 @@ BUILT_SOURCES += $(MNTENT_H)
 
 # We need the following in order to create <mntent.h> when desired.
 if GL_GENERATE_MNTENT_H
-mntent.h: mntent.in.h $(top_builddir)/config.status
+mntent.h: mntent.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
 	$(AM_V_GEN)$(MKDIR_P) '%reldir%'
 	$(AM_V_at)$(SED_HEADER_STDOUT) \
 	      -e 's|@''GUARD_PREFIX''@|${gl_include_guard_prefix}|g' \
@@ -27,6 +30,13 @@ mntent.h: mntent.in.h $(top_builddir)/config.status
 	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
 	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
 	      -e 's|@''NEXT_MNTENT_H''@|$(NEXT_MNTENT_H)|g' \
+	      -e 's/@''GNULIB_HASMNTOPT''@/$(GNULIB_HASMNTOPT)/g' \
+	      -e 's|@''HAVE_HASMNTOPT''@|$(HAVE_HASMNTOPT)|g' \
+	      -e 's|@''HAVE_SETMNTENT''@|$(HAVE_SETMNTENT)|g' \
+	      -e 's|@''REPLACE_HASMNTOPT''@|$(REPLACE_HASMNTOPT)|g' \
+	      -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+	      -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+	      -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
 	      $(srcdir)/mntent.in.h > $@-t
 	$(AM_V_at)mv $@-t $@
 else
-- 
2.34.1

>From b63008c3f1199f3abeb271338cc690a96b51dff3 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Mon, 19 Aug 2024 16:21:27 +0200
Subject: [PATCH 3/3] hasmntopt: Add tests.

* tests/test-hasmntopt.c: New file.
* modules/hasmntopt-tests: New file.
---
 ChangeLog               |  4 +++
 modules/hasmntopt-tests | 11 ++++++++
 tests/test-hasmntopt.c  | 60 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 75 insertions(+)
 create mode 100644 modules/hasmntopt-tests
 create mode 100644 tests/test-hasmntopt.c

diff --git a/ChangeLog b/ChangeLog
index 8cbd4b8a80..5b3996e920 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2024-08-19  Bruno Haible  <br...@clisp.org>
 
+	hasmntopt: Add tests.
+	* tests/test-hasmntopt.c: New file.
+	* modules/hasmntopt-tests: New file.
+
 	hasmntopt: New module.
 	* lib/mntent.in.h: Add config.h check.
 	(hasmntopt): New declaration.
diff --git a/modules/hasmntopt-tests b/modules/hasmntopt-tests
new file mode 100644
index 0000000000..a15dd29420
--- /dev/null
+++ b/modules/hasmntopt-tests
@@ -0,0 +1,11 @@
+Files:
+tests/test-hasmntopt.c
+tests/macros.h
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-hasmntopt
+check_PROGRAMS += test-hasmntopt
diff --git a/tests/test-hasmntopt.c b/tests/test-hasmntopt.c
new file mode 100644
index 0000000000..e4f0b380fe
--- /dev/null
+++ b/tests/test-hasmntopt.c
@@ -0,0 +1,60 @@
+/* Test of hasmntopt() function.
+   Copyright (C) 2024 Free Software Foundation, Inc.
+
+   This file is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   This file is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <br...@clisp.org>, 2024.  */
+
+#include <config.h>
+
+#if HAVE_SETMNTENT
+
+/* Specification.  */
+# include <mntent.h>
+
+# include "macros.h"
+
+int
+main ()
+{
+  char options[] = "rw,nosuid,nodev,noexec,relatime,size=5120k,inode64";
+  struct mntent me;
+  me.mnt_opts = options;
+
+  ASSERT (hasmntopt (&me, "ro") == NULL);
+  ASSERT (hasmntopt (&me, "rw") == options + 0);
+  ASSERT (hasmntopt (&me, "atime") == NULL);
+  ASSERT (hasmntopt (&me, "rela") == NULL);
+  ASSERT (hasmntopt (&me, "relatime") == options + 23);
+  ASSERT (hasmntopt (&me, "size") == options + 32);
+  ASSERT (hasmntopt (&me, "size=512") == NULL);
+  ASSERT (hasmntopt (&me, "size=5120k") == options + 32);
+  ASSERT (hasmntopt (&me, "inode64") == options + 43);
+
+  return test_exit_status;
+}
+
+#else
+
+# include <stdio.h>
+
+int
+main ()
+{
+  fputs ("Skipping test: no setmntent, getmntent, endmntent functions\n",
+         stderr);
+  return 77;
+}
+
+#endif
-- 
2.34.1

Reply via email to