From dbdf761187d7cccfad20a2899bab3dc77f379c3a Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 27 Jun 2025 22:32:33 -0700 Subject: [PATCH] Update from Gnulib by running admin/merge-gnulib --- build-aux/gitlog-to-changelog | 4 +- build-aux/install-sh | 4 +- build-aux/move-if-change | 4 +- build-aux/update-copyright | 4 +- doc/misc/texinfo.tex | 3 +- lib/_Noreturn.h | 38 +++----- lib/acl.h | 2 + lib/attribute.h | 5 +- lib/boot-time.h | 13 ++- lib/fcntl.in.h | 6 +- lib/file-has-acl.c | 173 ++++++++++++++++++++++++---------- lib/gettext.h | 67 ++++++++++--- lib/gnulib.mk.in | 18 ++++ lib/open.c | 117 ++++++++++++++--------- lib/qcopy-acl.c | 29 +++++- lib/regcomp.c | 53 ++++++----- lib/regexec.c | 2 +- lib/stat-time.h | 43 ++++++--- lib/stdckdint.in.h | 39 ++++++-- lib/stddef.in.h | 63 ++++++++----- lib/string.in.h | 27 ++++++ lib/sys_stat.in.h | 6 +- lib/unistd.in.h | 18 ++-- m4/acl.m4 | 16 ++-- m4/gnulib-common.m4 | 57 +++++------ m4/gnulib-comp.m4 | 8 +- m4/libgmp.m4 | 8 +- m4/open.m4 | 5 +- m4/stdckdint_h.m4 | 136 ++++++++++++++++++++++++++ m4/stddef_h.m4 | 18 ++-- 30 files changed, 711 insertions(+), 275 deletions(-) create mode 100644 m4/stdckdint_h.m4 diff --git a/build-aux/gitlog-to-changelog b/build-aux/gitlog-to-changelog index 2e34fc0d84c..0c751f95703 100755 --- a/build-aux/gitlog-to-changelog +++ b/build-aux/gitlog-to-changelog @@ -35,7 +35,7 @@ eval 'exec perl -wSx "$0" "$@"' if 0; -my $VERSION = '2024-07-17 02:20'; # UTC +my $VERSION = '2025-06-10 02:43'; # UTC # The definition above must lie within the first 8 lines in order # for the Emacs time-stamp write hook (at end) to update it. # If you change this file with Emacs, please let the write hook @@ -544,7 +544,7 @@ sub git_dir_option($) # eval: (add-hook 'before-save-hook 'time-stamp nil t) # time-stamp-line-limit: 50 # time-stamp-start: "my $VERSION = '" -# time-stamp-format: "%:y-%02m-%02d %02H:%02M" +# time-stamp-format: "%Y-%02m-%02d %02H:%02M" # time-stamp-time-zone: "UTC0" # time-stamp-end: "'; # UTC" # End: diff --git a/build-aux/install-sh b/build-aux/install-sh index 8a76989bbc4..1d8d9669646 100755 --- a/build-aux/install-sh +++ b/build-aux/install-sh @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2024-12-03.03; # UTC +scriptversion=2025-06-18.21; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -535,7 +535,7 @@ done # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp nil t) # time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-format: "%Y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff --git a/build-aux/move-if-change b/build-aux/move-if-change index 0674f34fcef..90b8152ad84 100755 --- a/build-aux/move-if-change +++ b/build-aux/move-if-change @@ -2,7 +2,7 @@ # Like mv $1 $2, but if the files are the same, just delete $1. # Status is zero if successful, nonzero otherwise. -VERSION='2024-07-04 10:56'; # UTC +VERSION='2025-06-10 02:42'; # UTC # The definition above must lie within the first 8 lines in order # for the Emacs time-stamp write hook (at end) to update it. # If you change this file with Emacs, please let the write hook @@ -78,7 +78,7 @@ fi ## Local Variables: ## eval: (add-hook 'before-save-hook 'time-stamp nil t) ## time-stamp-start: "VERSION='" -## time-stamp-format: "%:y-%02m-%02d %02H:%02M" +## time-stamp-format: "%Y-%02m-%02d %02H:%02M" ## time-stamp-time-zone: "UTC0" ## time-stamp-end: "'; # UTC" ## End: diff --git a/build-aux/update-copyright b/build-aux/update-copyright index 124c7d2e423..592bd8b2695 100755 --- a/build-aux/update-copyright +++ b/build-aux/update-copyright @@ -138,7 +138,7 @@ eval 'exec perl -wSx -0777 -pi "$0" "$@"' if 0; -my $VERSION = '2025-01-01.07:36'; # UTC +my $VERSION = '2025-06-10.02:42'; # UTC # The definition above must lie within the first 8 lines in order # for the Emacs time-stamp write hook (at end) to update it. # If you change this file with Emacs, please let the write hook @@ -301,7 +301,7 @@ if (!$found) # eval: (add-hook 'before-save-hook 'time-stamp nil t) # time-stamp-line-limit: 200 # time-stamp-start: "my $VERSION = '" -# time-stamp-format: "%:y-%02m-%02d.%02H:%02M" +# time-stamp-format: "%Y-%02m-%02d.%02H:%02M" # time-stamp-time-zone: "UTC0" # time-stamp-end: "'; # UTC" # End: diff --git a/doc/misc/texinfo.tex b/doc/misc/texinfo.tex index 3ebea93cb1d..3907525cf56 100644 --- a/doc/misc/texinfo.tex +++ b/doc/misc/texinfo.tex @@ -3,7 +3,7 @@ % Load plain if necessary, i.e., if running under initex. \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi % -\def\texinfoversion{2025-03-22.08} +\def\texinfoversion{2025-06-18.21} % % Copyright 1985, 1986, 1988, 1990-2025 Free Software Foundation, Inc. % @@ -9419,6 +9419,7 @@ \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0 {\safexrefname}}% \fi + \ignorespaces % ignore ends of line in aux file } % If working on a large document in chapters, it is convenient to diff --git a/lib/_Noreturn.h b/lib/_Noreturn.h index 0d452649fb2..8e63387914c 100644 --- a/lib/_Noreturn.h +++ b/lib/_Noreturn.h @@ -14,33 +14,25 @@ You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ +/* The _Noreturn keyword of C11. + Do not use [[noreturn]], because with it the syntax + extern _Noreturn void func (...); + would not be valid; such a declaration would be valid only with 'extern' + and '_Noreturn' swapped, or without the 'extern' keyword. However, some + AIX system header files and several gnulib header files use precisely + this syntax with 'extern'. So even though C23 deprecates _Noreturn, + it is currently more portable to prefer it to [[noreturn]]. + + Also, do not try to work around LLVM bug 59792 (clang 15 or earlier). + This rare bug can be worked around by compiling with 'clang -D_Noreturn=', + though the workaround may generate many false-alarm warnings. */ #ifndef _Noreturn -# if (defined __cplusplus \ - && ((201103 <= __cplusplus && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \ - || (defined _MSC_VER && 1900 <= _MSC_VER)) \ - && 0) - /* [[noreturn]] is not practically usable, because with it the syntax - extern _Noreturn void func (...); - would not be valid; such a declaration would only be valid with 'extern' - and '_Noreturn' swapped, or without the 'extern' keyword. However, some - AIX system header files and several gnulib header files use precisely - this syntax with 'extern'. */ -# define _Noreturn [[noreturn]] -# elif (defined __clang__ && __clang_major__ < 16 \ - && defined _GL_WORK_AROUND_LLVM_BUG_59792) - /* Compile with -D_GL_WORK_AROUND_LLVM_BUG_59792 to work around - that rare LLVM bug, though you may get many false-alarm warnings. */ -# define _Noreturn -# elif ((!defined __cplusplus || defined __clang__) \ - && (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \ - || (!defined __STRICT_ANSI__ \ - && (4 < __GNUC__ + (7 <= __GNUC_MINOR__) && !defined __clang__ \ - || (defined __apple_build_version__ \ - ? 6000000 <= __apple_build_version__ \ - : 3 < __clang_major__ + (5 <= __clang_minor__)))))) +# if 201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) /* _Noreturn works as-is. */ # elif (2 < __GNUC__ + (8 <= __GNUC_MINOR__) || defined __clang__ \ || 0x5110 <= __SUNPRO_C) + /* Prefer __attribute__ ((__noreturn__)) to plain _Noreturn even if the + latter works, as 'gcc -std=gnu99 -Wpedantic' warns about _Noreturn. */ # define _Noreturn __attribute__ ((__noreturn__)) # elif 1200 <= (defined _MSC_VER ? _MSC_VER : 0) # define _Noreturn __declspec (noreturn) diff --git a/lib/acl.h b/lib/acl.h index 90fd24e152d..e3c134fb41c 100644 --- a/lib/acl.h +++ b/lib/acl.h @@ -79,6 +79,8 @@ struct aclinfo bool acl_errno_valid (int) _GL_ATTRIBUTE_CONST; int file_has_acl (char const *, struct stat const *); int file_has_aclinfo (char const *restrict, struct aclinfo *restrict, int); +int fdfile_has_aclinfo (int, char const *restrict, + struct aclinfo *restrict, int); #if HAVE_LINUX_XATTR_H && HAVE_LISTXATTR bool aclinfo_has_xattr (struct aclinfo const *, char const *) diff --git a/lib/attribute.h b/lib/attribute.h index ae7bbe8e2cb..c85412d90af 100644 --- a/lib/attribute.h +++ b/lib/attribute.h @@ -50,8 +50,9 @@ - In a function declaration/definition with a storage-class specifier: between the storage-class specifier and the return type. - - Or after the parameter list, - ∙ but after ATTRIBUTE_NOTHROW if present. + - Or, in a function declaration: + after the parameter list, + ∙ but after ATTRIBUTE_NOTHROW if present. In other declarations, such as variable declarations: diff --git a/lib/boot-time.h b/lib/boot-time.h index 195839a2c53..7abfa12e444 100644 --- a/lib/boot-time.h +++ b/lib/boot-time.h @@ -29,11 +29,16 @@ extern "C" { /* Store the approximate time when the machine last booted in *P_BOOT_TIME, and return 0. If it cannot be determined, return -1. + If the machine is a container inside another host machine, + return the boot time of the container, not the host. + The difference can matter in GNU/Linux, where times in /proc/stat + might be relative to boot time of the host, not the container. + This function is not multithread-safe, since on many platforms it - invokes the functions setutxent, getutxent, endutxent. These - functions are needed because they may lock FILE (so that we don't - read garbage when a concurrent process writes to FILE), but their - drawback is that they have a common global state. */ + invokes the functions setutxent, getutxent, endutxent. + These functions may lock a file like /var/log/wtmp (so that we + don't read garbage when a concurrent process writes to that file), + but their drawback is that they have a common global state. */ extern int get_boot_time (struct timespec *p_boot_time); diff --git a/lib/fcntl.in.h b/lib/fcntl.in.h index d7f551b30f3..c5068ed48a0 100644 --- a/lib/fcntl.in.h +++ b/lib/fcntl.in.h @@ -209,7 +209,9 @@ _GL_WARN_ON_USE (open, "open is not always POSIX compliant - " # undef open # define open _open # endif -_GL_CXXALIAS_MDA (open, int, (const char *filename, int flags, ...)); +/* Need to cast, because in MSVC the parameter list of _open as a C++ function + is (const char *, int, int = 0). */ +_GL_CXXALIAS_MDA_CAST (open, int, (const char *filename, int flags, ...)); # else _GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...)); # endif @@ -313,7 +315,7 @@ _GL_WARN_ON_USE (openat, "openat is not portable - " #endif #ifndef O_DIRECTORY -# define O_DIRECTORY 0 +# define O_DIRECTORY 0x20000000 /* Try to not collide with system O_* flags. */ #endif #ifndef O_DSYNC diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c index 66b920c1ab2..a9cfbf3a16e 100644 --- a/lib/file-has-acl.c +++ b/lib/file-has-acl.c @@ -85,6 +85,13 @@ smack_new_label_from_path (MAYBE_UNUSED const char *path, { return -1; } +static ssize_t +smack_new_label_from_file (MAYBE_UNUSED int fd, + MAYBE_UNUSED const char *xattr, + MAYBE_UNUSED char **label) +{ + return -1; +} # endif static bool is_smack_enabled (void) @@ -115,14 +122,16 @@ aclinfo_may_indicate_xattr (struct aclinfo const *ai) static bool has_xattr (char const *xattr, struct aclinfo const *ai, - MAYBE_UNUSED char const *restrict name, MAYBE_UNUSED int flags) + int fd, char const *restrict name, int flags) { if (ai && aclinfo_has_xattr (ai, xattr)) return true; else if (!ai || aclinfo_may_indicate_xattr (ai)) { - int ret = ((flags & ACL_SYMLINK_FOLLOW ? getxattr : lgetxattr) - (name, xattr, NULL, 0)); + int ret = (fd < 0 + ? ((flags & ACL_SYMLINK_FOLLOW ? getxattr : lgetxattr) + (name, xattr, NULL, 0)) + : fgetxattr (fd, xattr, NULL, 0)); if (0 <= ret || (errno == ERANGE || errno == E2BIG)) return true; } @@ -145,11 +154,12 @@ aclinfo_has_xattr (struct aclinfo const *ai, char const *xattr) return false; } -/* Get attributes of the file NAME into AI, if USE_ACL. +/* Get attributes of the file FD aka NAME into AI, if USE_ACL. + Ignore FD if it is negative. If FLAGS & ACL_GET_SCONTEXT, also get security context. If FLAGS & ACL_SYMLINK_FOLLOW, follow symbolic links. */ static void -get_aclinfo (char const *name, struct aclinfo *ai, int flags) +get_aclinfo (int fd, char const *name, struct aclinfo *ai, int flags) { int scontext_err = ENOTSUP; ai->buf = ai->u.__gl_acl_ch; @@ -163,7 +173,9 @@ get_aclinfo (char const *name, struct aclinfo *ai, int flags) = (flags & ACL_SYMLINK_FOLLOW ? listxattr : llistxattr); while (true) { - ai->size = lsxattr (name, ai->buf, acl_alloc); + ai->size = (fd < 0 + ? lsxattr (name, ai->buf, acl_alloc) + : flistxattr (fd, ai->buf, acl_alloc)); if (0 < ai->size) break; ai->u.err = ai->size < 0 ? errno : 0; @@ -171,7 +183,9 @@ get_aclinfo (char const *name, struct aclinfo *ai, int flags) break; /* The buffer was too small. Find how large it should have been. */ - ssize_t size = lsxattr (name, NULL, 0); + ssize_t size = (fd < 0 + ? lsxattr (name, NULL, 0) + : flistxattr (fd, NULL, 0)); if (size <= 0) { ai->size = size; @@ -214,9 +228,13 @@ get_aclinfo (char const *name, struct aclinfo *ai, int flags) { if (ai->size < 0 || aclinfo_has_xattr (ai, XATTR_NAME_SMACK)) { - ssize_t r = smack_new_label_from_path (name, "security.SMACK64", - flags & ACL_SYMLINK_FOLLOW, - &ai->scontext); + static char const SMACK64[] = "security.SMACK64"; + ssize_t r = + (fd < 0 + ? smack_new_label_from_path (name, SMACK64, + flags & ACL_SYMLINK_FOLLOW, + &ai->scontext) + : smack_new_label_from_file (fd, SMACK64, &ai->scontext)); scontext_err = r < 0 ? errno : 0; } } @@ -226,8 +244,10 @@ get_aclinfo (char const *name, struct aclinfo *ai, int flags) if (ai->size < 0 || aclinfo_has_xattr (ai, XATTR_NAME_SELINUX)) { ssize_t r = - ((flags & ACL_SYMLINK_FOLLOW ? getfilecon : lgetfilecon) - (name, &ai->scontext)); + (fd < 0 + ? ((flags & ACL_SYMLINK_FOLLOW ? getfilecon : lgetfilecon) + (name, &ai->scontext)) + : fgetfilecon (fd, &ai->scontext)); scontext_err = r < 0 ? errno : 0; # ifndef SE_SELINUX_INLINE /* Gnulib's selinux-h module is not in use, so getfilecon and @@ -362,11 +382,14 @@ acl_nfs4_nontrivial (uint32_t *xattr, ssize_t nbytes) } #endif -#if (!USE_LINUX_XATTR && USE_ACL && HAVE_ACL_GET_FD \ - && !HAVE_ACL_EXTENDED_FILE && !HAVE_ACL_TYPE_EXTENDED \ - && !HAVE_ACL_GET_LINK_NP) -# include -# ifdef O_PATH +#if (!USE_LINUX_XATTR && USE_ACL && HAVE_ACL_GET_FILE \ + && !HAVE_ACL_EXTENDED_FILE && !HAVE_ACL_TYPE_EXTENDED) +/* FreeBSD, NetBSD >= 10, IRIX, Tru64, Cygwin >= 2.5 */ + +# if HAVE_ACL_GET_FD && !HAVE_ACL_GET_LINK_NP /* IRIX, Tru64, Cygwin >= 2.5 */ +# include +# ifdef O_PATH +# define acl_get_fd_np(fd, type) acl_get_fd (fd) /* Like acl_get_file, but do not follow symbolic links. */ static acl_t @@ -381,8 +404,24 @@ acl_get_link_np (char const *name, acl_type_t type) errno = err; return r; } -# define HAVE_ACL_GET_LINK_NP 1 +# define HAVE_ACL_GET_LINK_NP 1 +# endif # endif + +static acl_t +acl_get_fdfile (int fd, char const *name, acl_type_t type, int flags) +{ + acl_t (*get) (char const *, acl_type_t) = acl_get_file; +# if HAVE_ACL_GET_LINK_NP /* FreeBSD, NetBSD >= 10, Cygwin >= 2.5 */ + if (0 <= fd) + return acl_get_fd_np (fd, type); + if (! (flags & ACL_SYMLINK_FOLLOW)) + get = acl_get_link_np; +# else + /* Ignore FD and FLAGS, unfortunately. */ +# endif + return get (name, type); +} #endif /* Return 1 if NAME has a nontrivial access control list, @@ -398,14 +437,35 @@ acl_get_link_np (char const *name, acl_type_t type) If the d_type value is not known, use DT_UNKNOWN though this may be less efficient. */ int -file_has_aclinfo (MAYBE_UNUSED char const *restrict name, +file_has_aclinfo (char const *restrict name, struct aclinfo *restrict ai, int flags) +{ + return fdfile_has_aclinfo (-1, name, ai, flags); +} + +/* Return 1 if FD aka NAME has a nontrivial access control list, + 0 if ACLs are not supported, or if NAME has no or only a base ACL, + and -1 (setting errno) on error. Note callers can determine + if ACLs are not supported as errno is set in that case also. + Ignore FD if it is negative. + Set *AI to ACL info regardless of return value. + FLAGS should be a d_type value, optionally ORed with + - _GL_DT_NOTDIR if it is known that NAME is not a directory, + - ACL_GET_SCONTEXT to retrieve security context and return 1 if present, + - ACL_SYMLINK_FOLLOW to follow the link if NAME is a symbolic link; + otherwise do not follow them if possible. + If the d_type value is not known, use DT_UNKNOWN though this may be less + efficient. */ +int +fdfile_has_aclinfo (MAYBE_UNUSED int fd, + MAYBE_UNUSED char const *restrict name, + struct aclinfo *restrict ai, int flags) { MAYBE_UNUSED unsigned char d_type = flags & UCHAR_MAX; #if USE_LINUX_XATTR int initial_errno = errno; - get_aclinfo (name, ai, flags); + get_aclinfo (fd, name, ai, flags); if (!aclinfo_may_indicate_xattr (ai) && ai->size <= 0) { @@ -418,11 +478,11 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name, In earlier Fedora the two types of ACLs were mutually exclusive. Attempt to work correctly on both kinds of systems. */ - if (!has_xattr (XATTR_NAME_NFSV4_ACL, ai, name, flags)) + if (!has_xattr (XATTR_NAME_NFSV4_ACL, ai, fd, name, flags)) return - (has_xattr (XATTR_NAME_POSIX_ACL_ACCESS, ai, name, flags) + (has_xattr (XATTR_NAME_POSIX_ACL_ACCESS, ai, fd, name, flags) || ((d_type == DT_DIR || d_type == DT_UNKNOWN) - && has_xattr (XATTR_NAME_POSIX_ACL_DEFAULT, ai, name, flags))); + && has_xattr (XATTR_NAME_POSIX_ACL_DEFAULT, ai, fd, name, flags))); /* A buffer large enough to hold any trivial NFSv4 ACL. The max length of a trivial NFSv4 ACL is 6 words for owner, @@ -432,8 +492,10 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name, everyone is another word to hold "EVERYONE@". */ uint32_t buf[2 * (6 + 6 + 7)]; - int ret = ((flags & ACL_SYMLINK_FOLLOW ? getxattr : lgetxattr) - (name, XATTR_NAME_NFSV4_ACL, buf, sizeof buf)); + int ret = (fd < 0 + ? ((flags & ACL_SYMLINK_FOLLOW ? getxattr : lgetxattr) + (name, XATTR_NAME_NFSV4_ACL, buf, sizeof buf)) + : fgetxattr (fd, XATTR_NAME_NFSV4_ACL, buf, sizeof buf)); if (ret < 0) switch (errno) { @@ -467,20 +529,23 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name, /* On Linux, acl_extended_file is an optimized function: It only makes two calls to getxattr(), one for ACL_TYPE_ACCESS, one for ACL_TYPE_DEFAULT. */ - ret = ((flags & ACL_SYMLINK_FOLLOW - ? acl_extended_file - : acl_extended_file_nofollow) - (name)); + ret = (fd < 0 + ? ((flags & ACL_SYMLINK_FOLLOW + ? acl_extended_file + : acl_extended_file_nofollow) + (name)) + : acl_extended_fd (fd)); # elif HAVE_ACL_TYPE_EXTENDED /* Mac OS X */ /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS) and acl_get_file (name, ACL_TYPE_DEFAULT) always return NULL / EINVAL. There is no point in making these two useless calls. The real ACL is retrieved through - acl_get_file (name, ACL_TYPE_EXTENDED). */ - acl_t acl = ((flags & ACL_SYMLINK_FOLLOW - ? acl_get_file - : acl_get_link_np) - (name, ACL_TYPE_EXTENDED)); + ACL_TYPE_EXTENDED. */ + acl_t acl = + (fd < 0 + ? ((flags & ACL_SYMLINK_FOLLOW ? acl_get_file : acl_get_link_np) + (name, ACL_TYPE_EXTENDED)) + : acl_get_fd_np (fd, ACL_TYPE_EXTENDED)); if (acl) { ret = acl_extended_nontrivial (acl); @@ -489,13 +554,8 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name, else ret = -1; # else /* FreeBSD, NetBSD >= 10, IRIX, Tru64, Cygwin >= 2.5 */ - acl_t (*acl_get_file_or_link) (char const *, acl_type_t) = acl_get_file; -# if HAVE_ACL_GET_LINK_NP /* FreeBSD, NetBSD >= 10, Cygwin >= 2.5 */ - if (! (flags & ACL_SYMLINK_FOLLOW)) - acl_get_file_or_link = acl_get_link_np; -# endif - acl_t acl = acl_get_file_or_link (name, ACL_TYPE_ACCESS); + acl_t acl = acl_get_fdfile (fd, name, ACL_TYPE_ACCESS, flags); if (acl) { ret = acl_access_nontrivial (acl); @@ -517,7 +577,7 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name, && (d_type == DT_DIR || (d_type == DT_UNKNOWN && !(flags & _GL_DT_NOTDIR)))) { - acl = acl_get_file_or_link (name, ACL_TYPE_DEFAULT); + acl = acl_get_fdfile (fd, name, ACL_TYPE_DEFAULT, flags); if (acl) { # ifdef __CYGWIN__ /* Cygwin >= 2.5 */ @@ -562,7 +622,10 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name, /* Solaris 10 (newer version), which has additional API declared in (acl_t) and implemented in libsec (acl_set, acl_trivial, - acl_fromtext, ...). */ + acl_fromtext, ...). + + Ignore FD, unfortunately. That is better than mishandling + ZFS-style ACLs, as the general case code does. */ return acl_trivial (name); # else /* Solaris, Cygwin, general case */ @@ -586,7 +649,9 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name, for (;;) { - count = acl (name, GETACL, alloc, entries); + count = (fd < 0 + ? acl (name, GETACL, alloc, entries) + : facl (fd, GETACL, alloc, entries)); if (count < 0 && errno == ENOSPC) { /* Increase the size of the buffer. */ @@ -657,7 +722,9 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name, for (;;) { - count = acl (name, ACE_GETACL, alloc, entries); + count = (fd < 0 + ? acl (name, ACE_GETACL, alloc, entries) + : facl (fd, ACE_GETACL, alloc, entries)); if (count < 0 && errno == ENOSPC) { /* Increase the size of the buffer. */ @@ -722,7 +789,9 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name, struct acl_entry entries[NACLENTRIES]; int count; - count = getacl (name, NACLENTRIES, entries); + count = (fd < 0 + ? getacl (name, NACLENTRIES, entries) + : fgetacl (fd, NACLENTRIES, entries)); if (count < 0) { @@ -751,7 +820,8 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name, { struct stat statbuf; - if (stat (name, &statbuf) == -1 && errno != EOVERFLOW) + if ((fd < 0 ? stat (name, &statbuf) : fstat (fd, &statbuf)) < 0 + && errno != EOVERFLOW) return -1; return acl_nontrivial (count, entries); @@ -765,6 +835,7 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name, struct acl entries[NACLVENTRIES]; int count; + /* Ignore FD, unfortunately. */ count = acl ((char *) name, ACL_GET, NACLVENTRIES, entries); if (count < 0) @@ -809,7 +880,9 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name, /* The docs say that type being 0 is equivalent to ACL_ANY, but it is not true, in AIX 5.3. */ type.u64 = ACL_ANY; - if (aclx_get (name, 0, &type, aclbuf, &aclsize, &mode) >= 0) + if (0 <= (fd < 0 + ? aclx_get (name, 0, &type, aclbuf, &aclsize, &mode) + : aclx_fget (fd, 0, &type, aclbuf, &aclsize, &mode))) break; if (errno == ENOSYS) return 0; @@ -855,7 +928,10 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name, union { struct acl a; char room[4096]; } u; - if (statacl ((char *) name, STX_NORMAL, &u.a, sizeof (u)) < 0) + if ((fd < 0 + ? statacl ((char *) name, STX_NORMAL, &u.a, sizeof u) + : fstatacl (fd, STX_NORMAL, &u.a, sizeof u)) + < 0) return -1; return acl_nontrivial (&u.a); @@ -866,6 +942,7 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name, struct acl entries[NACLENTRIES]; int count; + /* Ignore FD, unfortunately. */ count = acl ((char *) name, ACL_GET, NACLENTRIES, entries); if (count < 0) diff --git a/lib/gettext.h b/lib/gettext.h index ea0c27e0002..fd6c62b7eb7 100644 --- a/lib/gettext.h +++ b/lib/gettext.h @@ -59,18 +59,61 @@ # endif # endif -/* Disabled NLS. - The casts to 'const char *' serve the purpose of producing warnings - for invalid uses of the value returned from these functions. - On pre-ANSI systems without 'const', the config.h file is supposed to - contain "#define const". */ -# undef gettext -# define gettext(Msgid) ((const char *) (Msgid)) -# undef dgettext -# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) -# undef dcgettext -# define dcgettext(Domainname, Msgid, Category) \ - ((void) (Category), dgettext (Domainname, Msgid)) +/* Disabled NLS. */ +# if defined __GNUC__ && !defined __clang__ && !defined __cplusplus +/* Use inline functions, to avoid warnings + warning: format not a string literal and no format arguments + that don't occur with enabled NLS. */ +/* The return type 'const char *' serves the purpose of producing warnings + for invalid uses of the value returned from these functions. */ +# if __GNUC__ >= 9 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wbuiltin-declaration-mismatch" +# endif +__attribute__ ((__always_inline__, __gnu_inline__)) extern inline +# if !defined(__sun) +const +# endif +char * +gettext (const char *msgid) +{ + return msgid; +} +__attribute__ ((__always_inline__, __gnu_inline__)) extern inline +# if !defined(__sun) +const +# endif +char * +dgettext (const char *domain, const char *msgid) +{ + (void) domain; + return msgid; +} +__attribute__ ((__always_inline__, __gnu_inline__)) extern inline +# if !defined(__sun) +const +# endif +char * +dcgettext (const char *domain, const char *msgid, int category) +{ + (void) domain; + (void) category; + return msgid; +} +# if __GNUC__ >= 9 +# pragma GCC diagnostic pop +# endif +# else +/* The casts to 'const char *' serve the purpose of producing warnings + for invalid uses of the value returned from these functions. */ +# undef gettext +# define gettext(Msgid) ((const char *) (Msgid)) +# undef dgettext +# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) +# undef dcgettext +# define dcgettext(Domainname, Msgid, Category) \ + ((void) (Category), dgettext (Domainname, Msgid)) +# endif # undef ngettext # define ngettext(Msgid1, Msgid2, N) \ ((N) == 1 \ diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index fb34cf2cc1d..bb147b69eed 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -739,6 +739,9 @@ HAVE_CANONICALIZE_FILE_NAME = @HAVE_CANONICALIZE_FILE_NAME@ HAVE_CHOWN = @HAVE_CHOWN@ HAVE_CLOSEDIR = @HAVE_CLOSEDIR@ HAVE_COPY_FILE_RANGE = @HAVE_COPY_FILE_RANGE@ +HAVE_CXX_STDCKDINT_H = @HAVE_CXX_STDCKDINT_H@ +HAVE_C_STDCKDINT_H = @HAVE_C_STDCKDINT_H@ +HAVE_C_UNREACHABLE = @HAVE_C_UNREACHABLE@ HAVE_DECL_DIRFD = @HAVE_DECL_DIRFD@ HAVE_DECL_ECVT = @HAVE_DECL_ECVT@ HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@ @@ -911,6 +914,7 @@ HAVE_SIGNED_WINT_T = @HAVE_SIGNED_WINT_T@ HAVE_SIGSET_T = @HAVE_SIGSET_T@ HAVE_SLEEP = @HAVE_SLEEP@ HAVE_SPAWN_H = @HAVE_SPAWN_H@ +HAVE_STDCKDINT_H = @HAVE_STDCKDINT_H@ HAVE_STDINT_H = @HAVE_STDINT_H@ HAVE_STPCPY = @HAVE_STPCPY@ HAVE_STPNCPY = @HAVE_STPNCPY@ @@ -960,6 +964,8 @@ HAVE_VASPRINTF = @HAVE_VASPRINTF@ HAVE_VDPRINTF = @HAVE_VDPRINTF@ HAVE_WCHAR_H = @HAVE_WCHAR_H@ HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@ +HAVE_WORKING_CXX_STDCKDINT_H = @HAVE_WORKING_CXX_STDCKDINT_H@ +HAVE_WORKING_C_STDCKDINT_H = @HAVE_WORKING_C_STDCKDINT_H@ HAVE_XSERVER = @HAVE_XSERVER@ HAVE__EXIT = @HAVE__EXIT@ IEEE754_H = @IEEE754_H@ @@ -1087,6 +1093,7 @@ NEXT_AS_FIRST_DIRECTIVE_GETOPT_H = @NEXT_AS_FIRST_DIRECTIVE_GETOPT_H@ NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H = @NEXT_AS_FIRST_DIRECTIVE_INTTYPES_H@ NEXT_AS_FIRST_DIRECTIVE_LIMITS_H = @NEXT_AS_FIRST_DIRECTIVE_LIMITS_H@ NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H = @NEXT_AS_FIRST_DIRECTIVE_SIGNAL_H@ +NEXT_AS_FIRST_DIRECTIVE_STDCKDINT_H = @NEXT_AS_FIRST_DIRECTIVE_STDCKDINT_H@ NEXT_AS_FIRST_DIRECTIVE_STDDEF_H = @NEXT_AS_FIRST_DIRECTIVE_STDDEF_H@ NEXT_AS_FIRST_DIRECTIVE_STDINT_H = @NEXT_AS_FIRST_DIRECTIVE_STDINT_H@ NEXT_AS_FIRST_DIRECTIVE_STDIO_H = @NEXT_AS_FIRST_DIRECTIVE_STDIO_H@ @@ -1107,6 +1114,7 @@ NEXT_GETOPT_H = @NEXT_GETOPT_H@ NEXT_INTTYPES_H = @NEXT_INTTYPES_H@ NEXT_LIMITS_H = @NEXT_LIMITS_H@ NEXT_SIGNAL_H = @NEXT_SIGNAL_H@ +NEXT_STDCKDINT_H = @NEXT_STDCKDINT_H@ NEXT_STDDEF_H = @NEXT_STDDEF_H@ NEXT_STDINT_H = @NEXT_STDINT_H@ NEXT_STDIO_H = @NEXT_STDIO_H@ @@ -3202,6 +3210,15 @@ BUILT_SOURCES += $(STDCKDINT_H) ifneq (,$(GL_GENERATE_STDCKDINT_H_CONDITION)) stdckdint.h: stdckdint.in.h $(top_builddir)/config.status $(gl_V_at)$(SED_HEADER_STDOUT) \ + -e 's|@''GUARD_PREFIX''@|GL|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_STDCKDINT_H''@|$(NEXT_STDCKDINT_H)|g' \ + -e 's|@''HAVE_C_STDCKDINT_H''@|$(HAVE_C_STDCKDINT_H)|g' \ + -e 's|@''HAVE_WORKING_C_STDCKDINT_H''@|$(HAVE_WORKING_C_STDCKDINT_H)|g' \ + -e 's|@''HAVE_CXX_STDCKDINT_H''@|$(HAVE_CXX_STDCKDINT_H)|g' \ + -e 's|@''HAVE_WORKING_CXX_STDCKDINT_H''@|$(HAVE_WORKING_CXX_STDCKDINT_H)|g' \ $(srcdir)/stdckdint.in.h > $@-t $(AM_V_at)mv $@-t $@ else @@ -3234,6 +3251,7 @@ stddef.h: stddef.in.h $(top_builddir)/config.status -e 's|@''STDDEF_NOT_IDEMPOTENT''@|$(STDDEF_NOT_IDEMPOTENT)|g' \ -e 's|@''REPLACE_NULL''@|$(REPLACE_NULL)|g' \ -e 's|@''HAVE_MAX_ALIGN_T''@|$(HAVE_MAX_ALIGN_T)|g' \ + -e 's|@''HAVE_C_UNREACHABLE''@|$(HAVE_C_UNREACHABLE)|g' \ $(srcdir)/stddef.in.h > $@-t $(AM_V_at)mv $@-t $@ else diff --git a/lib/open.c b/lib/open.c index 7415b48f81c..8356c14f5b3 100644 --- a/lib/open.c +++ b/lib/open.c @@ -55,24 +55,25 @@ orig_open (const char *filename, int flags, mode_t mode) #include #include -#ifndef REPLACE_OPEN_DIRECTORY -# define REPLACE_OPEN_DIRECTORY 0 +#ifndef OPEN_TRAILING_SLASH_BUG +# define OPEN_TRAILING_SLASH_BUG false #endif +#ifndef REPLACE_OPEN_DIRECTORY +# define REPLACE_OPEN_DIRECTORY false +#endif + +static int +lstatif (char const *filename, struct stat *st, int flags) +{ + return flags & O_NOFOLLOW ? lstat (filename, st) : stat (filename, st); +} + int open (const char *filename, int flags, ...) { - /* 0 = unknown, 1 = yes, -1 = no. */ -#if GNULIB_defined_O_CLOEXEC - int have_cloexec = -1; -#else - static int have_cloexec; -#endif + mode_t mode = 0; - mode_t mode; - int fd; - - mode = 0; if (flags & O_CREAT) { va_list arg; @@ -99,7 +100,6 @@ open (const char *filename, int flags, ...) filename = "NUL"; #endif -#if OPEN_TRAILING_SLASH_BUG /* Fail if one of O_CREAT, O_WRONLY, O_RDWR is specified and the filename ends in a slash, as POSIX says such a filename must name a directory : @@ -118,21 +118,55 @@ open (const char *filename, int flags, ...) directories, - if O_WRONLY or O_RDWR is specified, open() must fail because the file does not contain a '.' directory. */ - if ((flags & O_CREAT) - || (flags & O_ACCMODE) == O_RDWR - || (flags & O_ACCMODE) == O_WRONLY) + bool check_for_slash_bug; + if (OPEN_TRAILING_SLASH_BUG) { size_t len = strlen (filename); - if (len > 0 && filename[len - 1] == '/') + check_for_slash_bug = len && filename[len - 1] == '/'; + } + else + check_for_slash_bug = false; + + if (check_for_slash_bug + && (flags & O_CREAT + || (flags & O_ACCMODE) == O_RDWR + || (flags & O_ACCMODE) == O_WRONLY)) + { + errno = EISDIR; + return -1; + } + + /* With the trailing slash bug or without working O_DIRECTORY, check with + stat first lest we hang trying to open a fifo. Although there is + a race between this and opening the file, we can do no better. + After opening the file we will check again with fstat. */ + bool check_directory = + (check_for_slash_bug + || (!HAVE_WORKING_O_DIRECTORY && flags & O_DIRECTORY)); + if (check_directory) + { + struct stat statbuf; + if (lstatif (filename, &statbuf, flags) < 0) { - errno = EISDIR; + if (! (flags & O_CREAT && errno == ENOENT)) + return -1; + } + else if (!S_ISDIR (statbuf.st_mode)) + { + errno = ENOTDIR; return -1; } } + + /* 0 = unknown, 1 = yes, -1 = no. */ +#if GNULIB_defined_O_CLOEXEC + int have_cloexec = -1; +#else + static int have_cloexec; #endif - fd = orig_open (filename, - flags & ~(have_cloexec < 0 ? O_CLOEXEC : 0), mode); + int fd = orig_open (filename, + flags & ~(have_cloexec < 0 ? O_CLOEXEC : 0), mode); if (flags & O_CLOEXEC) { @@ -154,19 +188,21 @@ open (const char *filename, int flags, ...) #if REPLACE_FCHDIR /* Implementing fchdir and fdopendir requires the ability to open a directory file descriptor. If open doesn't support that (as on - mingw), we use a dummy file that behaves the same as directories + mingw), use a dummy file that behaves the same as directories on Linux (ie. always reports EOF on attempts to read()), and - override fstat() in fchdir.c to hide the fact that we have a - dummy. */ + override fstat in fchdir.c to hide the dummy. */ if (REPLACE_OPEN_DIRECTORY && fd < 0 && errno == EACCES - && ((flags & O_ACCMODE) == O_RDONLY - || (O_SEARCH != O_RDONLY && (flags & O_ACCMODE) == O_SEARCH))) + && ((flags & (O_ACCMODE | O_CREAT)) == O_RDONLY + || (O_SEARCH != O_RDONLY + && (flags & (O_ACCMODE | O_CREAT)) == O_SEARCH))) { struct stat statbuf; - if (stat (filename, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)) + if (check_directory + || (lstatif (filename, &statbuf, flags) == 0 + && S_ISDIR (statbuf.st_mode))) { /* Maximum recursion depth of 1. */ - fd = open ("/dev/null", flags, mode); + fd = open ("/dev/null", flags & ~O_DIRECTORY, mode); if (0 <= fd) fd = _gl_register_fd (fd, filename); } @@ -175,10 +211,8 @@ open (const char *filename, int flags, ...) } #endif -#if OPEN_TRAILING_SLASH_BUG - /* If the filename ends in a slash and fd does not refer to a directory, - then fail. - Rationale: POSIX says such a filename must name a directory + /* If checking for directories, fail if fd does not refer to a directory. + Rationale: A filename ending in slash cannot name a non-directory : "A pathname that contains at least one non- character and that ends with one or more trailing characters shall not be resolved @@ -186,23 +220,18 @@ open (const char *filename, int flags, ...) characters names an existing directory" If the named file without the slash is not a directory, open() must fail with ENOTDIR. */ - if (fd >= 0) + if (check_directory && 0 <= fd) { - /* We know len is positive, since open did not fail with ENOENT. */ - size_t len = strlen (filename); - if (filename[len - 1] == '/') + struct stat statbuf; + int r = fstat (fd, &statbuf); + if (r < 0 || !S_ISDIR (statbuf.st_mode)) { - struct stat statbuf; - - if (fstat (fd, &statbuf) >= 0 && !S_ISDIR (statbuf.st_mode)) - { - close (fd); - errno = ENOTDIR; - return -1; - } + int err = r < 0 ? errno : ENOTDIR; + close (fd); + errno = err; + return -1; } } -#endif #if REPLACE_FCHDIR if (!REPLACE_OPEN_DIRECTORY && 0 <= fd) diff --git a/lib/qcopy-acl.c b/lib/qcopy-acl.c index ad7966152aa..282f4b2d2a5 100644 --- a/lib/qcopy-acl.c +++ b/lib/qcopy-acl.c @@ -26,6 +26,7 @@ #if USE_XATTR # include +# include # include # if HAVE_LINUX_XATTR_H @@ -61,6 +62,7 @@ is_attr_permissions (const char *name, struct error_context *ctx) a valid file descriptor, use file descriptor operations, else use filename based operations on SRC_NAME. Likewise for DEST_DESC and DST_NAME. + MODE should be the source file's st_mode. If access control lists are not available, fchmod the target file to MODE. Also sets the non-permission bits of the destination file (S_ISUID, S_ISGID, S_ISVTX) to those from MODE if any are set. @@ -86,10 +88,29 @@ qcopy_acl (const char *src_name, int source_desc, const char *dst_name, Functions attr_copy_* return 0 in case we copied something OR nothing to copy */ if (ret == 0) - ret = source_desc <= 0 || dest_desc <= 0 - ? attr_copy_file (src_name, dst_name, is_attr_permissions, NULL) - : attr_copy_fd (src_name, source_desc, dst_name, dest_desc, - is_attr_permissions, NULL); + { + ret = source_desc <= 0 || dest_desc <= 0 + ? attr_copy_file (src_name, dst_name, is_attr_permissions, NULL) + : attr_copy_fd (src_name, source_desc, dst_name, dest_desc, + is_attr_permissions, NULL); + + /* Copying can fail with EOPNOTSUPP even when the source + permissions are trivial (Bug#78328). Don't report an error + in this case, as the chmod_or_fchmod suffices. */ + if (ret < 0 && errno == EOPNOTSUPP) + { + /* fdfile_has_aclinfo cares only about DT_DIR, _GL_DT_NOTDIR, + and DT_LNK (but DT_LNK is not possible here), + so use _GL_DT_NOTDIR | DT_UNKNOWN for other file types. */ + int flags = S_ISDIR (mode) ? DT_DIR : _GL_DT_NOTDIR | DT_UNKNOWN; + + struct aclinfo ai; + if (!fdfile_has_aclinfo (source_desc, src_name, &ai, flags)) + ret = 0; + aclinfo_free (&ai); + errno = EOPNOTSUPP; + } + } #else /* no XATTR, so we proceed the old dusty way */ struct permission_context ctx; diff --git a/lib/regcomp.c b/lib/regcomp.c index a23f289d7a1..878b65baf07 100644 --- a/lib/regcomp.c +++ b/lib/regcomp.c @@ -1001,21 +1001,25 @@ create_initial_state (re_dfa_t *dfa) Idx dest_idx = dfa->edests[node_idx].elems[0]; if (!re_node_set_contains (&init_nodes, dest_idx)) { - reg_errcode_t merge_err + err = re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx); - if (merge_err != REG_NOERROR) - return merge_err; + if (err != REG_NOERROR) + break; i = 0; } } } /* It must be the first time to invoke acquire_state. */ - dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0); - /* We don't check ERR here, since the initial state must not be NULL. */ + dfa->init_state + = (err == REG_NOERROR + ? re_acquire_state_context (&err, dfa, &init_nodes, 0) + : NULL); if (__glibc_unlikely (dfa->init_state == NULL)) - return err; - if (dfa->init_state->has_constraint) + { + /* Don't check ERR here, as the initial state must not be null. */ + } + else if (dfa->init_state->has_constraint) { dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes, CONTEXT_WORD); @@ -1025,17 +1029,13 @@ create_initial_state (re_dfa_t *dfa) &init_nodes, CONTEXT_NEWLINE | CONTEXT_BEGBUF); - if (__glibc_unlikely (dfa->init_state_word == NULL - || dfa->init_state_nl == NULL - || dfa->init_state_begbuf == NULL)) - return err; } else dfa->init_state_word = dfa->init_state_nl = dfa->init_state_begbuf = dfa->init_state; re_node_set_free (&init_nodes); - return REG_NOERROR; + return err; } /* If it is possible to do searching in single byte encoding instead of UTF-8 @@ -1677,12 +1677,11 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) { err = duplicate_node_closure (dfa, node, node, node, dfa->nodes[node].constraint); - if (__glibc_unlikely (err != REG_NOERROR)) - return err; } /* Expand each epsilon destination nodes. */ - if (IS_EPSILON_NODE(dfa->nodes[node].type)) + if (__glibc_likely (err == REG_NOERROR) + && IS_EPSILON_NODE (dfa->nodes[node].type)) for (i = 0; i < dfa->edests[node].nelem; ++i) { re_node_set eclosure_elem; @@ -1700,14 +1699,14 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) { err = calc_eclosure_iter (&eclosure_elem, dfa, edest, false); if (__glibc_unlikely (err != REG_NOERROR)) - return err; + break; } else eclosure_elem = dfa->eclosures[edest]; /* Merge the epsilon closure of 'edest'. */ err = re_node_set_merge (&eclosure, &eclosure_elem); if (__glibc_unlikely (err != REG_NOERROR)) - return err; + break; /* If the epsilon closure of 'edest' is incomplete, the epsilon closure of this node is also incomplete. */ if (dfa->eclosures[edest].nelem == 0) @@ -1717,12 +1716,18 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) } } - if (incomplete && !root) - dfa->eclosures[node].nelem = 0; + if (err != REG_NOERROR) + re_node_set_free (&eclosure); else - dfa->eclosures[node] = eclosure; - *new_set = eclosure; - return REG_NOERROR; + { + if (incomplete && !root) + dfa->eclosures[node].nelem = 0; + else + dfa->eclosures[node] = eclosure; + *new_set = eclosure; + } + + return err; } /* Functions for token which are used in the parser. */ @@ -3275,6 +3280,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, else { free_charset (mbcset); + mbcset = NULL; /* Build a tree for simple bracket. */ br_token.type = SIMPLE_BRACKET; br_token.opr.sbcset = sbcset; @@ -3288,7 +3294,8 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, *err = REG_ESPACE; parse_bracket_exp_free_return: re_free (sbcset); - free_charset (mbcset); + if (__glibc_likely (mbcset != NULL)) + free_charset (mbcset); return NULL; } diff --git a/lib/regexec.c b/lib/regexec.c index c5ab9b6649f..0d14ac35fe9 100644 --- a/lib/regexec.c +++ b/lib/regexec.c @@ -2271,7 +2271,7 @@ merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx, these destinations and the results of the transition table. */ pstate = mctx->state_log[cur_idx]; log_nodes = pstate->entrance_nodes; - if (next_state != NULL) + if (next_state != NULL && next_state->entrance_nodes != NULL) { table_nodes = next_state->entrance_nodes; *err = re_node_set_init_union (&next_nodes, table_nodes, diff --git a/lib/stat-time.h b/lib/stat-time.h index 69813932d5e..38315b9f569 100644 --- a/lib/stat-time.h +++ b/lib/stat-time.h @@ -117,6 +117,31 @@ get_stat_birthtime_ns (_GL_UNUSED struct stat const *st) # endif } +/* Constructs a 'struct timespec' with the given contents. + This macro / function is private to stat-time.h. */ +#if !defined __cplusplus +/* Use a C99 compound literal. + This is guaranteed to initialize also the padding bits, for example on + platforms where tv_sec is 64 bits and tv_nsec is 32 bits, thus avoiding + gcc -Wuse-of-uninitialized-value warnings. */ +# define _gl_make_timespec(sec,nsec) \ + (struct timespec) { .tv_sec = (sec), .tv_nsec = (nsec) } +#else +/* C++ does not have C99 compound literals. + A constructor invocation + timespec { (sec), (nsec) } + would make assumptions about the order of the fields of 'struct timespec', + which are not guaranteed by POSIX. So, use an inline function. */ +static inline struct timespec +_gl_make_timespec (time_t sec, long nsec) +{ + struct timespec ts; + ts.tv_sec = sec; + ts.tv_nsec = nsec; + return ts; +} +#endif + /* Return *ST's access time. */ _GL_STAT_TIME_INLINE struct timespec _GL_ATTRIBUTE_PURE get_stat_atime (struct stat const *st) @@ -124,8 +149,7 @@ get_stat_atime (struct stat const *st) #ifdef STAT_TIMESPEC return STAT_TIMESPEC (st, st_atim); #else - return (struct timespec) { .tv_sec = st->st_atime, - .tv_nsec = get_stat_atime_ns (st) }; + return _gl_make_timespec (st->st_atime, get_stat_atime_ns (st)); #endif } @@ -136,8 +160,7 @@ get_stat_ctime (struct stat const *st) #ifdef STAT_TIMESPEC return STAT_TIMESPEC (st, st_ctim); #else - return (struct timespec) { .tv_sec = st->st_ctime, - .tv_nsec = get_stat_ctime_ns (st) }; + return _gl_make_timespec (st->st_ctime, get_stat_ctime_ns (st)); #endif } @@ -148,8 +171,7 @@ get_stat_mtime (struct stat const *st) #ifdef STAT_TIMESPEC return STAT_TIMESPEC (st, st_mtim); #else - return (struct timespec) { .tv_sec = st->st_mtime, - .tv_nsec = get_stat_mtime_ns (st) }; + return _gl_make_timespec (st->st_mtime, get_stat_mtime_ns (st)); #endif } @@ -164,8 +186,7 @@ get_stat_birthtime (_GL_UNUSED struct stat const *st) || defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC) t = STAT_TIMESPEC (st, st_birthtim); #elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC - t = (struct timespec) { .tv_sec = st->st_birthtime, - .tv_nsec = st->st_birthtimensec }; + t = _gl_make_timespec (st->st_birthtime, st->st_birthtimensec); #elif defined _WIN32 && ! defined __CYGWIN__ /* Native Windows platforms (but not Cygwin) put the "file creation time" in st_ctime (!). See @@ -173,11 +194,11 @@ get_stat_birthtime (_GL_UNUSED struct stat const *st) # if _GL_WINDOWS_STAT_TIMESPEC t = st->st_ctim; # else - t = (struct timespec) { .tv_sec = st->st_ctime }; + t = _gl_make_timespec (st->st_ctime, 0); # endif #else /* Birth time is not supported. */ - t = (struct timespec) { .tv_sec = -1, .tv_nsec = -1 }; + t = _gl_make_timespec (-1, -1); #endif #if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \ @@ -189,7 +210,7 @@ get_stat_birthtime (_GL_UNUSED struct stat const *st) sometimes returns junk in the birth time fields; work around this bug if it is detected. */ if (! (t.tv_sec && 0 <= t.tv_nsec && t.tv_nsec < 1000000000)) - t = (struct timespec) { .tv_sec = -1, .tv_nsec = -1 }; + t = _gl_make_timespec (-1, -1); #endif return t; diff --git a/lib/stdckdint.in.h b/lib/stdckdint.in.h index 83277b728ee..bb9089b4a13 100644 --- a/lib/stdckdint.in.h +++ b/lib/stdckdint.in.h @@ -15,10 +15,30 @@ You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ -#ifndef _GL_STDCKDINT_H -#define _GL_STDCKDINT_H +#if __GNUC__ >= 3 +@PRAGMA_SYSTEM_HEADER@ +#endif +@PRAGMA_COLUMNS@ -#include "intprops-internal.h" +#ifndef _@GUARD_PREFIX@_STDCKDINT_H + +/* The include_next requires a split double-inclusion guard. */ +#if defined __cplusplus ? @HAVE_CXX_STDCKDINT_H@ : @HAVE_C_STDCKDINT_H@ +# @INCLUDE_NEXT@ @NEXT_STDCKDINT_H@ +#endif + +#ifndef _@GUARD_PREFIX@_STDCKDINT_H +#define _@GUARD_PREFIX@_STDCKDINT_H + +/* Do nothing but include the system header if it works properly. */ +# if defined __cplusplus ? !@HAVE_WORKING_CXX_STDCKDINT_H@ : !@HAVE_WORKING_C_STDCKDINT_H@ + +/* Avoid redefining macros. */ +# undef ckd_add +# undef ckd_sub +# undef ckd_mul + +# include "intprops-internal.h" /* Store into *R the low-order bits of A + B, A - B, A * B, respectively. Return 1 if the result overflows, 0 otherwise. @@ -26,10 +46,13 @@ bit-precise integer type, or an enumeration type. These are like the standard macros introduced in C23, except that - arguments should not have side effects. */ + arguments should not have side effects. The C++26 standard is + expected to add this header and it's macros. */ -#define ckd_add(r, a, b) ((bool) _GL_INT_ADD_WRAPV (a, b, r)) -#define ckd_sub(r, a, b) ((bool) _GL_INT_SUBTRACT_WRAPV (a, b, r)) -#define ckd_mul(r, a, b) ((bool) _GL_INT_MULTIPLY_WRAPV (a, b, r)) +# define ckd_add(r, a, b) ((bool) _GL_INT_ADD_WRAPV (a, b, r)) +# define ckd_sub(r, a, b) ((bool) _GL_INT_SUBTRACT_WRAPV (a, b, r)) +# define ckd_mul(r, a, b) ((bool) _GL_INT_MULTIPLY_WRAPV (a, b, r)) -#endif /* _GL_STDCKDINT_H */ +# endif /* defined __cplusplus ? @HAVE_WORKING_CXX_STDCKDINT_H@ : @HAVE_WORKING_C_STDCKDINT_H@ */ +#endif /* _@GUARD_PREFIX@_STDCKDINT_H */ +#endif /* _@GUARD_PREFIX@_STDCKDINT_H */ diff --git a/lib/stddef.in.h b/lib/stddef.in.h index dc689b8df80..e8c55ff1cdc 100644 --- a/lib/stddef.in.h +++ b/lib/stddef.in.h @@ -188,38 +188,57 @@ typedef union #endif /* ISO C 23 § 7.21.1 The unreachable macro */ -#ifndef unreachable +/* This macro is only usable in C, not in C++. + There is no way to define it as a macro in C++, because that would break code + that does + #include + ... std::unreachable() ... + Similarly, there is no way to define it as an inline function in C++, because + that would break code that does + #include + using std::unreachable; + As a workaround, we define a macro gl_unreachable, that is like unreachable, + but is usable in both C and C++. */ /* Code borrowed from verify.h. */ -# ifndef _GL_HAS_BUILTIN_UNREACHABLE -# if defined __clang_major__ && __clang_major__ < 5 -# define _GL_HAS_BUILTIN_UNREACHABLE 0 -# elif 4 < __GNUC__ + (5 <= __GNUC_MINOR__) && !defined __clang__ -# define _GL_HAS_BUILTIN_UNREACHABLE 1 -# elif defined __has_builtin -# define _GL_HAS_BUILTIN_UNREACHABLE __has_builtin (__builtin_unreachable) -# else -# define _GL_HAS_BUILTIN_UNREACHABLE 0 -# endif -# endif - -# if _GL_HAS_BUILTIN_UNREACHABLE -# define unreachable() __builtin_unreachable () -# elif 1200 <= _MSC_VER -# define unreachable() __assume (0) +#ifndef _GL_HAS_BUILTIN_UNREACHABLE +# if defined __clang_major__ && __clang_major__ < 5 +# define _GL_HAS_BUILTIN_UNREACHABLE 0 +# elif 4 < __GNUC__ + (5 <= __GNUC_MINOR__) && !defined __clang__ +# define _GL_HAS_BUILTIN_UNREACHABLE 1 +# elif defined __has_builtin +# define _GL_HAS_BUILTIN_UNREACHABLE __has_builtin (__builtin_unreachable) # else +# define _GL_HAS_BUILTIN_UNREACHABLE 0 +# endif +#endif + +#if _GL_HAS_BUILTIN_UNREACHABLE +# define gl_unreachable() __builtin_unreachable () +#elif 1200 <= _MSC_VER +# define gl_unreachable() __assume (0) +#elif !defined __cplusplus && @HAVE_C_UNREACHABLE@ +# define gl_unreachable() unreachable () +#else /* Declare abort(), without including . */ extern -# if defined __cplusplus +# if defined __cplusplus "C" -# endif +# endif _Noreturn void abort (void) -# if defined __cplusplus && (__GLIBC__ >= 2) +# if defined __cplusplus && (__GLIBC__ >= 2) _GL_ATTRIBUTE_NOTHROW -# endif +# endif ; -# define unreachable() abort () +# define gl_unreachable() abort () +#endif + +#if !defined __cplusplus && !@HAVE_C_UNREACHABLE@ +/* In C, define unreachable as a macro. */ + +# ifndef unreachable +# define unreachable() gl_unreachable () # endif #endif diff --git a/lib/string.in.h b/lib/string.in.h index e7642211685..e3d94b76c17 100644 --- a/lib/string.in.h +++ b/lib/string.in.h @@ -215,25 +215,49 @@ _GL_EXTERN_C void free (void *); /* Declarations for ISO C N3322. */ #if defined __GNUC__ && __GNUC__ >= 15 && !defined __clang__ _GL_EXTERN_C void *memcpy (void *__dest, const void *__src, size_t __n) +# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 + _GL_ATTRIBUTE_NOTHROW +# endif _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); _GL_EXTERN_C void *memccpy (void *__dest, const void *__src, int __c, size_t __n) +# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 + _GL_ATTRIBUTE_NOTHROW +# endif _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 4) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 4); _GL_EXTERN_C void *memmove (void *__dest, const void *__src, size_t __n) +# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 + _GL_ATTRIBUTE_NOTHROW +# endif _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); _GL_EXTERN_C char *strncpy (char *__dest, const char *__src, size_t __n) +# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 + _GL_ATTRIBUTE_NOTHROW +# endif _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); _GL_EXTERN_C char *strndup (const char *__s, size_t __n) +# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 + _GL_ATTRIBUTE_NOTHROW +# endif _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 2); _GL_EXTERN_C char *strncat (char *__dest, const char *__src, size_t __n) +# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 + _GL_ATTRIBUTE_NOTHROW +# endif _GL_ARG_NONNULL ((1)) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); _GL_EXTERN_C int memcmp (const void *__s1, const void *__s2, size_t __n) +# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 + _GL_ATTRIBUTE_NOTHROW +# endif _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); _GL_EXTERN_C int strncmp (const char *__s1, const char *__s2, size_t __n) +# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 + _GL_ATTRIBUTE_NOTHROW +# endif _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (2, 3); # ifndef __cplusplus @@ -243,6 +267,9 @@ _GL_EXTERN_C void *memrchr (const void *__s, int __c, size_t __n) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3); # endif _GL_EXTERN_C void *memset (void *__s, int __c, size_t __n) +# if __GLIBC__ + (__GLIBC_MINOR__ >= 2) > 2 + _GL_ATTRIBUTE_NOTHROW +# endif _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3); _GL_EXTERN_C void *memset_explicit (void *__s, int __c, size_t __n) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (1, 3); diff --git a/lib/sys_stat.in.h b/lib/sys_stat.in.h index 8bde5a7d631..c3c38fd653e 100644 --- a/lib/sys_stat.in.h +++ b/lib/sys_stat.in.h @@ -849,7 +849,11 @@ _GL_WARN_ON_USE (mknodat, "mknodat is not portable - " # elif @WINDOWS_64_BIT_ST_SIZE@ /* Above, we define stat to _stati64. */ # if defined __MINGW32__ && defined _stati64 -# ifndef _USE_32BIT_TIME_T +# ifdef _USE_32BIT_TIME_T + /* The system headers possibly define _stati64 to _stat32i64. */ +# undef _stat32i64 +# define _stat32i64(name, st) rpl_stat (name, st) +# else /* The system headers define _stati64 to _stat64. */ # undef _stat64 # define _stat64(name, st) rpl_stat (name, st) diff --git a/lib/unistd.in.h b/lib/unistd.in.h index c135a770dc1..9f057d30cdf 100644 --- a/lib/unistd.in.h +++ b/lib/unistd.in.h @@ -95,6 +95,15 @@ # include #endif +/* Native Windows platforms declare _chdir, _getcwd, _rmdir in + and/or , not in . + They also declare _access(), _chmod(), _close(), _dup(), _dup2(), _isatty(), + _lseek(), _read(), _unlink(), _write() in . */ +#if defined _WIN32 && !defined __CYGWIN__ +# include +# include +#endif + /* FreeBSD 14.0, NetBSD 10.0, OpenBSD 7.5, Solaris 11.4, and glibc 2.41 do not define O_CLOEXEC in . */ /* Cygwin 1.7.1 and Android 4.3 declare unlinkat in , not in @@ -120,15 +129,6 @@ # undef __need_system_stdlib_h #endif -/* Native Windows platforms declare _chdir, _getcwd, _rmdir in - and/or , not in . - They also declare _access(), _chmod(), _close(), _dup(), _dup2(), _isatty(), - _lseek(), _read(), _unlink(), _write() in . */ -#if defined _WIN32 && !defined __CYGWIN__ -# include -# include -#endif - /* Native Windows platforms declare _execl*, _execv* in . */ #if defined _WIN32 && !defined __CYGWIN__ # include diff --git a/m4/acl.m4 b/m4/acl.m4 index 7e4b0e354d9..2dd33497efd 100644 --- a/m4/acl.m4 +++ b/m4/acl.m4 @@ -1,5 +1,5 @@ # acl.m4 -# serial 35 +# serial 37 dnl Copyright (C) 2002, 2004-2025 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -12,7 +12,6 @@ dnl This file is offered as-is, without any warranty. AC_DEFUN([gl_FUNC_ACL_ARG], [ - gl_need_lib_has_acl= AC_ARG_ENABLE([acl], AS_HELP_STRING([[--disable-acl]], [do not support ACLs]), , [enable_acl=auto]) @@ -22,6 +21,7 @@ AC_DEFUN([gl_FUNC_ACL_ARG], [], [with_libsmack=maybe]) ]) +# Prerequisites of module acl-permissions. AC_DEFUN_ONCE([gl_FUNC_ACL], [ AC_REQUIRE([gl_FUNC_ACL_ARG]) @@ -145,9 +145,6 @@ int type = ACL_TYPE_EXTENDED;]])], AC_MSG_WARN([AC_PACKAGE_NAME will be built without ACL support.]) fi fi - if test -n "$gl_need_lib_has_acl"; then - FILE_HAS_ACL_LIB=$LIB_ACL - fi AC_SUBST([LIB_ACL]) AC_DEFINE_UNQUOTED([USE_ACL], [$use_acl], [Define to nonzero if you want access control list support.]) @@ -187,6 +184,7 @@ AC_DEFUN([gl_ACL_GET_FILE], AC_DEFUN([gl_FILE_HAS_ACL], [ AC_REQUIRE([gl_FUNC_ACL_ARG]) + AC_REQUIRE([gl_FUNC_ACL]) # On GNU/Linux, testing if a file has an acl can be done with the # listxattr and getxattr syscalls, which don't require linking # against additional libraries. Assume this works if linux/attr.h @@ -224,10 +222,7 @@ AC_DEFUN([gl_FILE_HAS_ACL], AS_CASE([$enable_acl,$gl_file_has_acl_uses_selinux,$gl_file_has_acl_uses_smack], [no,* | *,yes,* | *,yes], [], [*], - [dnl Set gl_need_lib_has_acl to a nonempty value, so that any - dnl later gl_FUNC_ACL call will set FILE_HAS_ACL_LIB=$LIB_ACL. - gl_need_lib_has_acl=1 - FILE_HAS_ACL_LIB=$LIB_ACL]) + [FILE_HAS_ACL_LIB=$LIB_ACL]) AC_SUBST([FILE_HAS_ACL_LIB]) ]) @@ -235,10 +230,11 @@ AC_DEFUN([gl_FILE_HAS_ACL], AC_DEFUN([gl_QCOPY_ACL], [ AC_REQUIRE([gl_FUNC_ACL]) + AC_REQUIRE([gl_FILE_HAS_ACL]) AC_CHECK_HEADERS_ONCE([linux/xattr.h]) gl_FUNC_XATTR if test "$use_xattr" = yes; then - QCOPY_ACL_LIB="$LIB_XATTR" + QCOPY_ACL_LIB="$LIB_XATTR $FILE_HAS_ACL_LIB" else QCOPY_ACL_LIB="$LIB_ACL" fi diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4 index a07c7dd5a89..d525d8b1faa 100644 --- a/m4/gnulib-common.m4 +++ b/m4/gnulib-common.m4 @@ -1,5 +1,5 @@ # gnulib-common.m4 -# serial 110 +# serial 112 dnl Copyright (C) 2007-2025 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -57,33 +57,24 @@ AC_DEFUN([gl_COMMON_BODY], [ #endif ]) AH_VERBATIM([_Noreturn], -[/* The _Noreturn keyword of C11. */ +[/* The _Noreturn keyword of C11. + Do not use [[noreturn]], because with it the syntax + extern _Noreturn void func (...); + would not be valid; such a declaration would be valid only with 'extern' + and '_Noreturn' swapped, or without the 'extern' keyword. However, some + AIX system header files and several gnulib header files use precisely + this syntax with 'extern'. So even though C23 deprecates _Noreturn, + it is currently more portable to prefer it to [[noreturn]]. + + Also, do not try to work around LLVM bug 59792 (clang 15 or earlier). + This rare bug can be worked around by compiling with 'clang -D_Noreturn=', + though the workaround may generate many false-alarm warnings. */ #ifndef _Noreturn -# if (defined __cplusplus \ - && ((201103 <= __cplusplus && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \ - || (defined _MSC_VER && 1900 <= _MSC_VER)) \ - && 0) - /* [[noreturn]] is not practically usable, because with it the syntax - extern _Noreturn void func (...); - would not be valid; such a declaration would only be valid with 'extern' - and '_Noreturn' swapped, or without the 'extern' keyword. However, some - AIX system header files and several gnulib header files use precisely - this syntax with 'extern'. */ -# define _Noreturn [[noreturn]] -# elif (defined __clang__ && __clang_major__ < 16 \ - && defined _GL_WORK_AROUND_LLVM_BUG_59792) - /* Compile with -D_GL_WORK_AROUND_LLVM_BUG_59792 to work around - that rare LLVM bug, though you may get many false-alarm warnings. */ -# define _Noreturn -# elif ((!defined __cplusplus || defined __clang__) \ - && (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \ - || (!defined __STRICT_ANSI__ \ - && (_GL_GNUC_PREREQ (4, 7) \ - || (defined __apple_build_version__ \ - ? 6000000 <= __apple_build_version__ \ - : 3 < __clang_major__ + (5 <= __clang_minor__)))))) +# if 201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) /* _Noreturn works as-is. */ # elif _GL_GNUC_PREREQ (2, 8) || defined __clang__ || 0x5110 <= __SUNPRO_C + /* Prefer __attribute__ ((__noreturn__)) to plain _Noreturn even if the + latter works, as 'gcc -std=gnu99 -Wpedantic' warns about _Noreturn. */ # define _Noreturn __attribute__ ((__noreturn__)) # elif 1200 <= (defined _MSC_VER ? _MSC_VER : 0) # define _Noreturn __declspec (noreturn) @@ -955,8 +946,8 @@ AC_DEFUN([gl_COMMON_BODY], [ -1 if n1 < n2 The naïve code (n1 > n2 ? 1 : n1 < n2 ? -1 : 0) produces a conditional jump with nearly all GCC versions up to GCC 10. - This variant (n1 < n2 ? -1 : n1 > n2) produces a conditional with many - GCC versions up to GCC 9. + This variant (n1 < n2 ? -1 : n1 > n2) produces a conditional jump with + many GCC versions up to GCC 9. The better code (n1 > n2) - (n1 < n2) from Hacker's Delight § 2-9 avoids conditional jumps in all GCC versions >= 3.4. */ #define _GL_CMP(n1, n2) (((n1) > (n2)) - ((n1) < (n2))) @@ -1571,13 +1562,25 @@ AC_DEFUN([gl_CHECK_FUNCS_CASE_FOR_MACOS], if test $[ac_cv_func_][$1] = yes; then [gl_cv_onwards_func_][$1]=yes else + dnl This is a bit complicated, because here we need the behaviour + dnl of AC_CHECK_DECL before the + dnl commit e1bbc9b93cdff61d70719c224b37970e065008bb (2025-05-26). + [ac_cv_have_decl_][$1][_saved]="$[ac_cv_have_decl_][$1]" unset [ac_cv_have_decl_][$1] + ac_c_future_darwin_options_saved="$ac_c_future_darwin_options" + ac_cxx_future_darwin_options_saved="$ac_cxx_future_darwin_options" + ac_c_future_darwin_options= + ac_cxx_future_darwin_options= AC_CHECK_DECL([$1], , , [$2]) + ac_c_future_darwin_options="$ac_c_future_darwin_options_saved" + ac_cxx_future_darwin_options="$ac_cxx_future_darwin_options_saved" if test $[ac_cv_have_decl_][$1] = yes; then [gl_cv_onwards_func_][$1]='future OS version' else [gl_cv_onwards_func_][$1]=no fi + [ac_cv_have_decl_][$1]="$[ac_cv_have_decl_][$1][_saved]" + unset [ac_cv_have_decl_][$1][_saved] fi else AC_CHECK_FUNC([$1]) diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index 97db7d32a66..7e6a8a5494f 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 @@ -547,12 +547,7 @@ AC_DEFUN([gl_INIT], GL_STDC_LEADING_ZEROS=1 AC_REQUIRE([gl_STDBIT_H]) GL_STDC_TRAILING_ZEROS=1 - AC_CHECK_HEADERS_ONCE([stdckdint.h]) - if test $ac_cv_header_stdckdint_h = yes; then - GL_GENERATE_STDCKDINT_H=false - else - GL_GENERATE_STDCKDINT_H=true - fi + gl_STDCKDINT_H gl_CONDITIONAL_HEADER([stdckdint.h]) AC_PROG_MKDIR_P gl_STDDEF_H @@ -1558,6 +1553,7 @@ AC_DEFUN([gl_FILE_LIST], [ m4/std-gnu11.m4 m4/stdalign.m4 m4/stdbit_h.m4 + m4/stdckdint_h.m4 m4/stddef_h.m4 m4/stdint.m4 m4/stdio_h.m4 diff --git a/m4/libgmp.m4 b/m4/libgmp.m4 index baed8ab1a0a..abf677949dd 100644 --- a/m4/libgmp.m4 +++ b/m4/libgmp.m4 @@ -1,5 +1,5 @@ # libgmp.m4 -# serial 8 +# serial 9 # Configure the GMP library or a replacement. dnl Copyright 2020-2025 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation @@ -34,7 +34,11 @@ AC_DEFUN([gl_LIBGMP], # include #else # include - #endif], + #endif + #if ! (6 < __GNU_MP_VERSION + (2 <= __GNU_MP_VERSION_MINOR)) + # error "GMP < 6.2.0, so mpz_probab_prime_p lacks Baillie-PSW" + #endif + ], [static const mp_limb_t x[2] = { 0x73, 0x55 }; mpz_t tmp; mpz_roinit_n (tmp, x, 2); diff --git a/m4/open.m4 b/m4/open.m4 index 2bceddbdbe3..dd3a805f5e9 100644 --- a/m4/open.m4 +++ b/m4/open.m4 @@ -1,5 +1,5 @@ # open.m4 -# serial 16 +# serial 17 dnl Copyright (C) 2007-2025 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -10,6 +10,9 @@ AC_DEFUN([gl_FUNC_OPEN], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([gl_PREPROC_O_CLOEXEC]) + AC_REQUIRE([gl_FCNTL_O_FLAGS]) + AS_CASE([$gl_cv_header_working_fcntl_h], + [*O_DIRECTORY* | *no], [REPLACE_OPEN=1]) case "$host_os" in mingw* | windows* | pw*) REPLACE_OPEN=1 diff --git a/m4/stdckdint_h.m4 b/m4/stdckdint_h.m4 new file mode 100644 index 00000000000..d269faa5c92 --- /dev/null +++ b/m4/stdckdint_h.m4 @@ -0,0 +1,136 @@ +# stdckdint_h.m4 +# serial 1 +dnl Copyright 2025 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. +dnl This file is offered as-is, without any warranty. + +dnl Written by Collin Funk. + +AC_DEFUN_ONCE([gl_STDCKDINT_H], +[ + gl_CHECK_NEXT_HEADERS([stdckdint.h]) + if test $ac_cv_header_stdckdint_h = yes; then + HAVE_STDCKDINT_H=1 + else + HAVE_STDCKDINT_H=0 + fi + AC_SUBST([HAVE_STDCKDINT_H]) + + if test $HAVE_STDCKDINT_H = 1; then + AC_CACHE_CHECK([whether stdckdint.h can be included in C], + [gl_cv_header_c_stdckdint_h], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + ]])], + [gl_cv_header_c_stdckdint_h=yes], + [gl_cv_header_c_stdckdint_h=no])]) + if test $gl_cv_header_c_stdckdint_h = yes; then + HAVE_C_STDCKDINT_H=1 + AC_CACHE_CHECK([checking for an ISO C23 compliant stdckdint.h in C], + [gl_cv_header_c_stdckdint_h_works], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + ]], + [[int r; + int a = 1; + int b = 1; + return !!(ckd_add (&r, a, b) || ckd_sub (&r, a, b) + || ckd_mul (&r, a, b)); + ]])], + [gl_cv_header_c_stdckdint_h_works=yes], + [gl_cv_header_c_stdckdint_h_works=no])]) + if test $gl_cv_header_c_stdckdint_h_works = yes; then + HAVE_WORKING_C_STDCKDINT_H=1 + else + HAVE_WORKING_C_STDCKDINT_H=0 + fi + else + HAVE_C_STDCKDINT_H=0 + HAVE_WORKING_C_STDCKDINT_H=0 + fi + if test "$CXX" != no; then + AC_CACHE_CHECK([whether stdckdint.h can be included in C++], + [gl_cv_header_cxx_stdckdint_h], + [dnl We can't use AC_LANG_PUSH([C++]) and AC_LANG_POP([C++]) here, due to + dnl an autoconf bug . + cat > conftest.cpp <<\EOF +#include +EOF + gl_command="$CXX $CXXFLAGS $CPPFLAGS -c conftest.cpp" + if AC_TRY_EVAL([gl_command]); then + gl_cv_header_cxx_stdckdint_h=yes + else + gl_cv_header_cxx_stdckdint_h=no + fi + rm -fr conftest* + ]) + if test $gl_cv_header_cxx_stdckdint_h = yes; then + HAVE_CXX_STDCKDINT_H=1 + AC_CACHE_CHECK([checking for an ISO C++26 compliant stdckdint.h in C++], + [gl_cv_header_cxx_stdckdint_h_works], + [dnl We can't use AC_LANG_PUSH([C++]) and AC_LANG_POP([C++]) here, due to + dnl an autoconf bug . + cat > conftest.cpp <<\EOF +#include +int +main (void) +{ + int r; + int a = 1; + int b = 1; + return !!(ckd_add (&r, a, b) || ckd_sub (&r, a, b) || ckd_mul (&r, a, b)); +} +EOF + gl_command="$CXX $CXXFLAGS $CPPFLAGS -c conftest.cpp" + if AC_TRY_EVAL([gl_command]); then + gl_cv_header_cxx_stdckdint_h_works=yes + else + gl_cv_header_cxx_stdckdint_h_works=no + fi + rm -fr conftest* + ]) + if test $gl_cv_header_cxx_stdckdint_h_works = yes; then + HAVE_WORKING_CXX_STDCKDINT_H=1 + else + HAVE_WORKING_CXX_STDCKDINT_H=0 + fi + else + HAVE_CXX_STDCKDINT_H=0 + HAVE_WORKING_CXX_STDCKDINT_H=0 + fi + fi + else + HAVE_C_STDCKDINT_H=0 + HAVE_WORKING_C_STDCKDINT_H=0 + HAVE_CXX_STDCKDINT_H=0 + HAVE_WORKING_CXX_STDCKDINT_H=0 + fi + AC_SUBST([HAVE_C_STDCKDINT_H]) + AC_SUBST([HAVE_WORKING_C_STDCKDINT_H]) + AC_SUBST([HAVE_CXX_STDCKDINT_H]) + AC_SUBST([HAVE_WORKING_CXX_STDCKDINT_H]) + + if test "$CXX" != no; then + dnl We might need the header for C or C++. + if test $HAVE_C_STDCKDINT_H = 1 \ + && test $HAVE_WORKING_C_STDCKDINT_H = 1 \ + && test $HAVE_CXX_STDCKDINT_H = 1 \ + && test $HAVE_WORKING_CXX_STDCKDINT_H = 1; then + GL_GENERATE_STDCKDINT_H=false + else + GL_GENERATE_STDCKDINT_H=true + fi + else + dnl We don't care about C++ here. + if test $HAVE_C_STDCKDINT_H = 1 \ + && test $HAVE_WORKING_C_STDCKDINT_H = 1; then + GL_GENERATE_STDCKDINT_H=false + else + GL_GENERATE_STDCKDINT_H=true + fi + fi +]) diff --git a/m4/stddef_h.m4 b/m4/stddef_h.m4 index 3bc8cd85fea..127ec05b60d 100644 --- a/m4/stddef_h.m4 +++ b/m4/stddef_h.m4 @@ -1,5 +1,5 @@ # stddef_h.m4 -# serial 21 +# serial 23 dnl Copyright (C) 2009-2025 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -64,20 +64,26 @@ AC_DEFUN_ONCE([gl_STDDEF_H], GL_GENERATE_STDDEF_H=true fi - AC_CACHE_CHECK([for unreachable], - [gl_cv_func_unreachable], + AC_CACHE_CHECK([for unreachable in C], + [gl_cv_c_func_unreachable], [AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[#include ]], [[unreachable (); ]])], - [gl_cv_func_unreachable=yes], - [gl_cv_func_unreachable=no]) + [gl_cv_c_func_unreachable=yes], + [gl_cv_c_func_unreachable=no]) ]) - if test $gl_cv_func_unreachable = no; then + if test $gl_cv_c_func_unreachable = no; then GL_GENERATE_STDDEF_H=true + HAVE_C_UNREACHABLE=0 + else + HAVE_C_UNREACHABLE=1 fi + AC_SUBST([HAVE_C_UNREACHABLE]) + dnl Provide gl_unreachable() unconditionally. + GL_GENERATE_STDDEF_H=true dnl https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114869 AC_CACHE_CHECK([whether nullptr_t needs ],