summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2024-12-17 14:02:41 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2024-12-17 14:13:54 -0800
commitb1e5f6d6ef8432a9cce0664238de72d387730bd1 (patch)
tree7eb50047793367bf8f2483e28fb716cfc4334c13 /lib
parent22806c65f4f8d68547d33997d017039763b4bf6a (diff)
Update from Gnulib by running admin/merge-gnulib
* admin/merge-gnulib (AVOIDED_MODULES): Avoid gnulib-i18n. * lib/stdlib.c, m4/selinux-selinux-h.m4: New files, taken from Gnulib.
Diffstat (limited to 'lib')
-rw-r--r--lib/acl-internal.c6
-rw-r--r--lib/acl.h59
-rw-r--r--lib/dirent.in.h95
-rw-r--r--lib/file-has-acl.c571
-rw-r--r--lib/getopt-cdefs.in.h10
-rw-r--r--lib/getopt-pfx-core.h7
-rw-r--r--lib/getopt.c4
-rw-r--r--lib/gettext.h32
-rw-r--r--lib/gnulib.mk.in50
-rw-r--r--lib/malloc.c11
-rw-r--r--lib/md5-stream.c3
-rw-r--r--lib/md5.h8
-rw-r--r--lib/memset_explicit.c5
-rw-r--r--lib/mini-gmp.c95
-rw-r--r--lib/mini-gmp.h1
-rw-r--r--lib/mktime-internal.h9
-rw-r--r--lib/mktime.c111
-rw-r--r--lib/nproc.c41
-rw-r--r--lib/pipe2.c2
-rw-r--r--lib/realloc.c71
-rw-r--r--lib/regex.h18
-rw-r--r--lib/regex_internal.c3
-rw-r--r--lib/regex_internal.h10
-rw-r--r--lib/stdio-impl.h2
-rw-r--r--lib/stdlib.c21
-rw-r--r--lib/stdlib.in.h43
-rw-r--r--lib/timegm.c3
-rw-r--r--lib/unistd.in.h5
-rw-r--r--lib/utimens.c68
-rw-r--r--lib/utimens.h10
30 files changed, 942 insertions, 432 deletions
diff --git a/lib/acl-internal.c b/lib/acl-internal.c
index ae5398306af..b729126118a 100644
--- a/lib/acl-internal.c
+++ b/lib/acl-internal.c
@@ -19,10 +19,12 @@
#include <config.h>
-#include "acl.h"
-
+/* Specification. */
+#define ACL_INTERNAL_INLINE _GL_EXTERN_INLINE
#include "acl-internal.h"
+#include "acl.h"
+
#if defined __CYGWIN__
# include <sys/types.h>
# include <grp.h>
diff --git a/lib/acl.h b/lib/acl.h
index 475231c2db7..1d52345c668 100644
--- a/lib/acl.h
+++ b/lib/acl.h
@@ -32,9 +32,68 @@
extern "C" {
#endif
+/* file_has_acl flags guaranteed to not collide with any <dirent.h>
+ DT_* or _GL_DT_* value. */
+enum
+ {
+ /* Get scontext information as well. */
+ ACL_GET_SCONTEXT = 0x10000,
+
+ /* Follow symlinks. */
+ ACL_SYMLINK_FOLLOW = 0x20000,
+ };
+
+/* Information about an ACL. */
+struct aclinfo
+{
+ /* If 'size' is nonnegative, a buffer holding the concatenation
+ of extended attribute names, each terminated by NUL
+ (either u.__gl_acl_ch, or heap-allocated). */
+ char *buf;
+
+ /* The number of useful bytes at the start of buf, counting trailing NULs.
+ If negative, there was an error in getting the ACL info,
+ and u.err is the corresponding errno. */
+ ssize_t size;
+
+ /* Security context string. Do not modify its contents. */
+ char *scontext;
+ /* Security context errno value. It is zero if there was no
+ error getting the security context. When nonzero, scontext is "?". */
+ int scontext_err;
+
+ union
+ {
+ /* An errno value, when there was an error getting the ACL info. */
+ int err;
+
+ /* A small array of char, big enough for most listxattr results.
+ The size is somewhat arbitrary; it equals the max length of a
+ trivial NFSv4 ACL (a size used by file-has-acl.c in 2023-2024
+ but no longer relevant now), and a different value might be
+ better once experience is gained. For internal use only. */
+ char __gl_acl_ch[152];
+ } u;
+};
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);
+
+#if HAVE_LINUX_XATTR_H && HAVE_LISTXATTR
+bool aclinfo_has_xattr (struct aclinfo const *, char const *)
+ _GL_ATTRIBUTE_PURE;
+void aclinfo_free (struct aclinfo *);
+#else
+# define aclinfo_has_xattr(ai, xattr) false
+# define aclinfo_free(ai) ((void) 0)
+#endif
+#if (HAVE_LINUX_XATTR_H && HAVE_LISTXATTR \
+ && (HAVE_SMACK || USE_SELINUX_SELINUX_H))
+void aclinfo_scontext_free (char *);
+#else
+# define aclinfo_scontext_free(s) ((void) 0)
+#endif
int qset_acl (char const *, int, mode_t);
int xset_acl (char const *, int, mode_t);
diff --git a/lib/dirent.in.h b/lib/dirent.in.h
index 7ba8fc64d89..a0ac39b4968 100644
--- a/lib/dirent.in.h
+++ b/lib/dirent.in.h
@@ -46,20 +46,95 @@ struct dirent
char d_type;
char d_name[1];
};
-/* Possible values for 'd_type'. */
-# define DT_UNKNOWN 0
-# define DT_FIFO 1 /* FIFO */
-# define DT_CHR 2 /* character device */
-# define DT_DIR 4 /* directory */
-# define DT_BLK 6 /* block device */
-# define DT_REG 8 /* regular file */
-# define DT_LNK 10 /* symbolic link */
-# define DT_SOCK 12 /* socket */
-# define DT_WHT 14 /* whiteout */
# define GNULIB_defined_struct_dirent 1
# endif
#endif
+/* 'd_type' macros specified in GNU, i.e., POSIX.1-2024 plus DT_WHT,
+ but not (yet) DT_MQ, DT_SEM, DT_SHM, DT_TMO.
+ These macros can be useful even on platforms that do not support
+ d_type or the corresponding file types.
+ The values of these macros are all in the 'unsigned char' range.
+ Default to the Linux values which are also popular elsewhere,
+ and check that all macros have distinct values. */
+#ifndef DT_UNKNOWN
+# define DT_UNKNOWN 0
+#endif
+#ifndef DT_FIFO
+# define DT_FIFO 1 /* FIFO */
+#endif
+#ifndef DT_CHR
+# define DT_CHR 2 /* character device */
+#endif
+#ifndef DT_DIR
+# define DT_DIR 4 /* directory */
+#endif
+#ifndef DT_BLK
+# define DT_BLK 6 /* block device */
+#endif
+#ifndef DT_REG
+# define DT_REG 8 /* regular file */
+#endif
+#ifndef DT_LNK
+# define DT_LNK 10 /* symbolic link */
+#endif
+#ifndef DT_SOCK
+# define DT_SOCK 12 /* socket */
+#endif
+#ifndef DT_WHT
+# define DT_WHT 14 /* whiteout */
+#endif
+static_assert (DT_UNKNOWN != DT_FIFO && DT_UNKNOWN != DT_CHR
+ && DT_UNKNOWN != DT_BLK && DT_UNKNOWN != DT_REG
+ && DT_UNKNOWN != DT_LNK && DT_UNKNOWN != DT_SOCK
+ && DT_UNKNOWN != DT_WHT
+ && DT_FIFO != DT_CHR && DT_FIFO != DT_BLK && DT_FIFO != DT_REG
+ && DT_FIFO != DT_LNK && DT_FIFO != DT_SOCK && DT_FIFO != DT_WHT
+ && DT_CHR != DT_BLK && DT_CHR != DT_REG && DT_CHR != DT_LNK
+ && DT_CHR != DT_SOCK && DT_CHR != DT_WHT
+ && DT_BLK != DT_REG && DT_BLK != DT_LNK && DT_BLK != DT_SOCK
+ && DT_BLK != DT_WHT
+ && DT_REG != DT_LNK && DT_REG != DT_SOCK && DT_REG != DT_WHT
+ && DT_LNK != DT_SOCK && DT_LNK != DT_WHT
+ && DT_SOCK != DT_WHT);
+
+/* Other optional information about a directory entry. */
+#define _GL_DT_NOTDIR 0x100 /* Not a directory */
+
+/* Conversion between S_IF* and DT_* file types. */
+#if ! (defined IFTODT && defined DTTOIF)
+# include <sys/stat.h>
+# ifdef S_ISWHT
+# define _GL_DIRENT_S_ISWHT(mode) S_ISWHT(mode)
+# else
+# define _GL_DIRENT_S_ISWHT(mode) 0
+# endif
+# ifdef S_IFWHT
+# define _GL_DIRENT_S_IFWHT S_IFWHT
+# else
+# define _GL_DIRENT_S_IFWHT (DT_WHT << 12) /* just a guess */
+# endif
+#endif
+/* Conversion from a 'stat' mode to a DT_* value. */
+#ifndef IFTODT
+# define IFTODT(mode) \
+ (S_ISREG (mode) ? DT_REG : S_ISDIR (mode) ? DT_DIR \
+ : S_ISLNK (mode) ? DT_LNK : S_ISBLK (mode) ? DT_BLK \
+ : S_ISCHR (mode) ? DT_CHR : S_ISFIFO (mode) ? DT_FIFO \
+ : S_ISSOCK (mode) ? DT_SOCK \
+ : _GL_DIRENT_S_ISWHT (mode) ? DT_WHT : DT_UNKNOWN)
+#endif
+/* Conversion from a DT_* value to a 'stat' mode. */
+#ifndef DTTOIF
+# define DTTOIF(dirtype) \
+ ((dirtype) == DT_REG ? S_IFREG : (dirtype) == DT_DIR ? S_IFDIR \
+ : (dirtype) == DT_LNK ? S_IFLNK : (dirtype) == DT_BLK ? S_IFBLK \
+ : (dirtype) == DT_CHR ? S_IFCHR : dirtype == DT_FIFO ? S_IFIFO \
+ : (dirtype) == DT_SOCK ? S_IFSOCK \
+ : (dirtype) == DT_WHT ? _GL_DIRENT_S_IFWHT \
+ : (dirtype) << 12 /* just a guess */)
+#endif
+
#if !@DIR_HAS_FD_MEMBER@
# if !GNULIB_defined_DIR
/* struct gl_directory is a type with a field 'int fd_to_close'.
diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c
index 06759a4948c..7c29f201589 100644
--- a/lib/file-has-acl.c
+++ b/lib/file-has-acl.c
@@ -27,12 +27,30 @@
#include "acl.h"
+#include <dirent.h>
+#include <limits.h>
+
#include "acl-internal.h"
#include "attribute.h"
#include "minmax.h"
-#if USE_ACL && HAVE_LINUX_XATTR_H && HAVE_LISTXATTR
+/* Check the assumption that UCHAR_MAX < INT_MAX. */
+static_assert (ACL_SYMLINK_FOLLOW & ~ (unsigned char) -1);
+
+static char const UNKNOWN_SECURITY_CONTEXT[] = "?";
+
+#if HAVE_LINUX_XATTR_H && HAVE_LISTXATTR
+# define USE_LINUX_XATTR true
+#else
+# define USE_LINUX_XATTR false
+#endif
+
+#if USE_LINUX_XATTR
+# if USE_SELINUX_SELINUX_H
+# include <selinux/selinux.h>
+# endif
# include <stdckdint.h>
+# include <stdint.h>
# include <string.h>
# include <arpa/inet.h>
# include <sys/xattr.h>
@@ -47,26 +65,186 @@
# define XATTR_NAME_POSIX_ACL_DEFAULT "system.posix_acl_default"
# endif
+# ifdef HAVE_SMACK
+# include <sys/smack.h>
+# else
+static char const *
+smack_smackfs_path (void)
+{
+ return NULL;
+}
+static ssize_t
+smack_new_label_from_path (MAYBE_UNUSED const char *path,
+ MAYBE_UNUSED const char *xattr,
+ MAYBE_UNUSED int follow, MAYBE_UNUSED char **label)
+{
+ return -1;
+}
+# endif
+static bool
+is_smack_enabled (void)
+{
+ return !!smack_smackfs_path ();
+}
+
enum {
/* ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000, */
ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001,
ACE4_IDENTIFIER_GROUP = 0x00000040
};
-/* Return true if ATTR is in the set represented by the NUL-terminated
- strings in LISTBUF, which is of size LISTSIZE. */
+/* Does AI's xattr set contain XATTR? */
-ATTRIBUTE_PURE static bool
-have_xattr (char const *attr, char const *listbuf, ssize_t listsize)
+bool
+aclinfo_has_xattr (struct aclinfo const *ai, char const *xattr)
{
- char const *blim = listbuf + listsize;
- for (char const *b = listbuf; b < blim; b += strlen (b) + 1)
- for (char const *a = attr; *a == *b; a++, b++)
- if (!*a)
- return true;
+ if (0 < ai->size)
+ {
+ char const *blim = ai->buf + ai->size;
+ for (char const *b = ai->buf; b < blim; b += strlen (b) + 1)
+ for (char const *a = xattr; *a == *b; a++, b++)
+ if (!*a)
+ return true;
+ }
return false;
}
+/* Get attributes of the file NAME into AI, if USE_ACL.
+ 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)
+{
+ int scontext_err = ENOTSUP;
+ ai->buf = ai->u.__gl_acl_ch;
+ ssize_t acl_alloc = sizeof ai->u.__gl_acl_ch;
+
+ if (! (USE_ACL || flags & ACL_GET_SCONTEXT))
+ ai->size = 0;
+ else
+ {
+ ssize_t (*lsxattr) (char const *, char *, size_t)
+ = (flags & ACL_SYMLINK_FOLLOW ? listxattr : llistxattr);
+ while (true)
+ {
+ ai->size = lsxattr (name, ai->buf, acl_alloc);
+ if (0 < ai->size)
+ break;
+ ai->u.err = ai->size < 0 ? errno : 0;
+ if (! (ai->size < 0 && ai->u.err == ERANGE && acl_alloc < SSIZE_MAX))
+ break;
+
+ /* The buffer was too small. Find how large it should have been. */
+ ssize_t size = lsxattr (name, NULL, 0);
+ if (size <= 0)
+ {
+ ai->size = size;
+ ai->u.err = size < 0 ? errno : 0;
+ break;
+ }
+
+ /* Grow allocation to at least 'size'. Grow it by a nontrivial
+ amount, to defend against denial of service by an adversary
+ that fiddles with ACLs. */
+ if (ai->buf != ai->u.__gl_acl_ch)
+ {
+ free (ai->buf);
+ ai->buf = ai->u.__gl_acl_ch;
+ }
+ if (ckd_add (&acl_alloc, acl_alloc, acl_alloc >> 1))
+ acl_alloc = SSIZE_MAX;
+ if (acl_alloc < size)
+ acl_alloc = size;
+ if (SIZE_MAX < acl_alloc)
+ {
+ ai->u.err = ENOMEM;
+ break;
+ }
+ char *newbuf = malloc (acl_alloc);
+ if (!newbuf)
+ {
+ ai->u.err = errno;
+ break;
+ }
+ ai->buf = newbuf;
+ }
+ }
+
+ if (0 < ai->size && flags & ACL_GET_SCONTEXT)
+ {
+ if (is_smack_enabled ())
+ {
+ if (aclinfo_has_xattr (ai, XATTR_NAME_SMACK))
+ {
+ ssize_t r = smack_new_label_from_path (name, "security.SMACK64",
+ flags & ACL_SYMLINK_FOLLOW,
+ &ai->scontext);
+ scontext_err = r < 0 ? errno : 0;
+ }
+ }
+ else
+ {
+# if USE_SELINUX_SELINUX_H
+ if (aclinfo_has_xattr (ai, XATTR_NAME_SELINUX))
+ {
+ ssize_t r =
+ ((flags & ACL_SYMLINK_FOLLOW ? getfilecon : lgetfilecon)
+ (name, &ai->scontext));
+ scontext_err = r < 0 ? errno : 0;
+# ifndef SE_SELINUX_INLINE
+ /* Gnulib's selinux-h module is not in use, so getfilecon and
+ lgetfilecon can misbehave, be it via an old version of
+ libselinux where these would return 0 and set the result
+ context to NULL, or via a modern kernel+lib operating on a
+ file from a disk whose attributes were set by a kernel from
+ around 2006. In that latter case, the functions return a
+ length of 10 for the "unlabeled" context. Map both failures
+ to a return value of -1, and set errno to ENOTSUP in the
+ first case, and ENODATA in the latter. */
+ if (r == 0)
+ scontext_err = ENOTSUP;
+ if (r == 10 && memcmp (ai->scontext, "unlabeled", 10) == 0)
+ {
+ freecon (ai->scontext);
+ scontext_err = ENODATA;
+ }
+# endif
+ }
+# endif
+ }
+ }
+ ai->scontext_err = scontext_err;
+ if (scontext_err)
+ ai->scontext = (char *) UNKNOWN_SECURITY_CONTEXT;
+}
+
+# ifndef aclinfo_scontext_free
+/* Free the pointer that file_has_aclinfo put into scontext.
+ However, do nothing if the argument is a null pointer;
+ This lets the caller replace the scontext member with a null pointer if it
+ is willing to own the member and call this function later. */
+void
+aclinfo_scontext_free (char *scontext)
+{
+ if (scontext != UNKNOWN_SECURITY_CONTEXT)
+ {
+ if (is_smack_enabled ())
+ free (scontext);
+ else if (scontext)
+ freecon (scontext);
+ }
+}
+# endif
+
+/* Free AI's heap storage. */
+void
+aclinfo_free (struct aclinfo *ai)
+{
+ if (ai->buf != ai->u.__gl_acl_ch)
+ free (ai->buf);
+ aclinfo_scontext_free (ai->scontext);
+}
+
/* Return 1 if given ACL in XDR format is non-trivial, 0 if it is trivial.
-1 upon failure to determine it. Possibly change errno. Assume that
the ACL is valid, except avoid undefined behavior even if invalid.
@@ -150,196 +328,183 @@ acl_nfs4_nontrivial (uint32_t *xattr, ssize_t nbytes)
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.
- SB must be set to the stat buffer of NAME,
- obtained through stat() or lstat(). */
-
+ Set *AI to ACL info regardless of return value.
+ FLAGS should be a <dirent.h> 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
-file_has_acl (char const *name, struct stat const *sb)
+file_has_aclinfo (MAYBE_UNUSED char const *restrict name,
+ struct aclinfo *restrict ai, int flags)
{
-#if USE_ACL
- if (! S_ISLNK (sb->st_mode))
- {
+ MAYBE_UNUSED unsigned char d_type = flags & UCHAR_MAX;
-# if HAVE_LINUX_XATTR_H && HAVE_LISTXATTR
- int initial_errno = errno;
+#if USE_LINUX_XATTR
+ int initial_errno = errno;
+ get_aclinfo (name, ai, flags);
- /* The max length of a trivial NFSv4 ACL is 6 words for owner,
- 6 for group, 7 for everyone, all times 2 because there are
- both allow and deny ACEs. There are 6 words for owner
- because of type, flag, mask, wholen, "OWNER@"+pad and
- similarly for group; everyone is another word to hold
- "EVERYONE@". */
- typedef uint32_t trivial_NFSv4_xattr_buf[2 * (6 + 6 + 7)];
+ if (ai->size <= 0)
+ {
+ errno = ai->size < 0 ? ai->u.err : initial_errno;
+ return ai->size;
+ }
- /* A buffer large enough to hold any trivial NFSv4 ACL,
- and also useful as a small array of char. */
- union {
- trivial_NFSv4_xattr_buf xattr;
- char ch[sizeof (trivial_NFSv4_xattr_buf)];
- } stackbuf;
+ /* In Fedora 39, a file can have both NFSv4 and POSIX ACLs,
+ but if it has an NFSv4 ACL that's the one that matters.
+ In earlier Fedora the two types of ACLs were mutually exclusive.
+ Attempt to work correctly on both kinds of systems. */
- char *listbuf = stackbuf.ch;
- ssize_t listbufsize = sizeof stackbuf.ch;
- char *heapbuf = NULL;
- ssize_t listsize;
+ if (!aclinfo_has_xattr (ai, XATTR_NAME_NFSV4_ACL))
+ return
+ (aclinfo_has_xattr (ai, XATTR_NAME_POSIX_ACL_ACCESS)
+ || ((d_type == DT_DIR || d_type == DT_UNKNOWN)
+ && aclinfo_has_xattr (ai, XATTR_NAME_POSIX_ACL_DEFAULT)));
- /* Use listxattr first, as this means just one syscall in the
- typical case where the file lacks an ACL. Try stackbuf
- first, falling back on malloc if stackbuf is too small. */
- while ((listsize = listxattr (name, listbuf, listbufsize)) < 0
- && errno == ERANGE)
- {
- free (heapbuf);
- ssize_t newsize = listxattr (name, NULL, 0);
- if (newsize <= 0)
- return newsize;
+ /* A buffer large enough to hold any trivial NFSv4 ACL.
+ The max length of a trivial NFSv4 ACL is 6 words for owner,
+ 6 for group, 7 for everyone, all times 2 because there are both
+ allow and deny ACEs. There are 6 words for owner because of
+ type, flag, mask, wholen, "OWNER@"+pad and similarly for group;
+ everyone is another word to hold "EVERYONE@". */
+ uint32_t buf[2 * (6 + 6 + 7)];
- /* Grow LISTBUFSIZE to at least NEWSIZE. Grow it by a
- nontrivial amount too, to defend against denial of
- service by an adversary that fiddles with ACLs. */
- bool overflow = ckd_add (&listbufsize, listbufsize, listbufsize >> 1);
- listbufsize = MAX (listbufsize, newsize);
- if (overflow || SIZE_MAX < listbufsize)
- {
- errno = ENOMEM;
- return -1;
- }
+ int ret = ((flags & ACL_SYMLINK_FOLLOW ? getxattr : lgetxattr)
+ (name, XATTR_NAME_NFSV4_ACL, buf, sizeof buf));
+ if (ret < 0)
+ switch (errno)
+ {
+ case ENODATA: return 0;
+ case ERANGE : return 1; /* ACL must be nontrivial. */
+ default: return - acl_errno_valid (errno);
+ }
- listbuf = heapbuf = malloc (listbufsize);
- if (!listbuf)
- return -1;
- }
+ /* It looks like a trivial ACL, but investigate further. */
+ ret = acl_nfs4_nontrivial (buf, ret);
+ errno = ret < 0 ? EINVAL : initial_errno;
+ return ret;
- /* In Fedora 39, a file can have both NFSv4 and POSIX ACLs,
- but if it has an NFSv4 ACL that's the one that matters.
- In earlier Fedora the two types of ACLs were mutually exclusive.
- Attempt to work correctly on both kinds of systems. */
- bool nfsv4_acl
- = 0 < listsize && have_xattr (XATTR_NAME_NFSV4_ACL, listbuf, listsize);
- int ret
- = (listsize <= 0 ? listsize
- : (nfsv4_acl
- || have_xattr (XATTR_NAME_POSIX_ACL_ACCESS, listbuf, listsize)
- || (S_ISDIR (sb->st_mode)
- && have_xattr (XATTR_NAME_POSIX_ACL_DEFAULT,
- listbuf, listsize))));
- free (heapbuf);
+#else /* !USE_LINUX_XATTR */
- /* If there is an NFSv4 ACL, follow up with a getxattr syscall
- to see whether the NFSv4 ACL is nontrivial. */
- if (nfsv4_acl)
- {
- ret = getxattr (name, XATTR_NAME_NFSV4_ACL,
- stackbuf.xattr, sizeof stackbuf.xattr);
- if (ret < 0)
- switch (errno)
- {
- case ENODATA: return 0;
- case ERANGE : return 1; /* ACL must be nontrivial. */
- }
- else
- {
- /* It looks like a trivial ACL, but investigate further. */
- ret = acl_nfs4_nontrivial (stackbuf.xattr, ret);
- if (ret < 0)
- {
- errno = EINVAL;
- return ret;
- }
- errno = initial_errno;
- }
- }
- if (ret < 0)
- return - acl_errno_valid (errno);
- return ret;
+ ai->buf = ai->u.__gl_acl_ch;
+ ai->size = -1;
+ ai->u.err = ENOTSUP;
+ ai->scontext = (char *) UNKNOWN_SECURITY_CONTEXT;
+ ai->scontext_err = ENOTSUP;
-# elif HAVE_ACL_GET_FILE
+# if USE_ACL
+# if HAVE_ACL_GET_FILE
- /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */
- /* Linux, FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */
- int ret;
+ {
+ /* POSIX 1003.1e (draft 17 -- abandoned) specific version. */
+ /* Linux, FreeBSD, NetBSD >= 10, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */
+ int ret;
- if (HAVE_ACL_EXTENDED_FILE) /* Linux */
- {
- /* 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 = acl_extended_file (name);
- }
- else /* FreeBSD, Mac OS X, IRIX, Tru64, Cygwin >= 2.5 */
- {
-# if 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 = acl_get_file (name, ACL_TYPE_EXTENDED);
- if (acl)
- {
- ret = acl_extended_nontrivial (acl);
- acl_free (acl);
- }
- else
- ret = -1;
-# else /* FreeBSD, IRIX, Tru64, Cygwin >= 2.5 */
- acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS);
- if (acl)
- {
- int saved_errno;
+# if HAVE_ACL_EXTENDED_FILE /* Linux */
+ /* 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));
+# 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));
+ if (acl)
+ {
+ ret = acl_extended_nontrivial (acl);
+ acl_free (acl);
+ }
+ 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 */
+ if (! (flags & ACL_SYMLINK_FOLLOW))
+ acl_get_file_or_link = acl_get_link_np;
+# endif
- ret = acl_access_nontrivial (acl);
- saved_errno = errno;
- acl_free (acl);
- errno = saved_errno;
-# if HAVE_ACL_FREE_TEXT /* Tru64 */
- /* On OSF/1, acl_get_file (name, ACL_TYPE_DEFAULT) always
- returns NULL with errno not set. There is no point in
- making this call. */
-# else /* FreeBSD, IRIX, Cygwin >= 2.5 */
- /* On Linux, FreeBSD, IRIX, acl_get_file (name, ACL_TYPE_ACCESS)
- and acl_get_file (name, ACL_TYPE_DEFAULT) on a directory
- either both succeed or both fail; it depends on the
- file system. Therefore there is no point in making the second
- call if the first one already failed. */
- if (ret == 0 && S_ISDIR (sb->st_mode))
- {
- acl = acl_get_file (name, ACL_TYPE_DEFAULT);
- if (acl)
- {
-# ifdef __CYGWIN__ /* Cygwin >= 2.5 */
- ret = acl_access_nontrivial (acl);
- saved_errno = errno;
- acl_free (acl);
- errno = saved_errno;
-# else
- ret = (0 < acl_entries (acl));
- acl_free (acl);
+ acl_t acl = acl_get_file_or_link (name, ACL_TYPE_ACCESS);
+ if (acl)
+ {
+ ret = acl_access_nontrivial (acl);
+ int saved_errno = errno;
+ acl_free (acl);
+ errno = saved_errno;
+# if HAVE_ACL_FREE_TEXT /* Tru64 */
+ /* On OSF/1, acl_get_file (name, ACL_TYPE_DEFAULT) always
+ returns NULL with errno not set. There is no point in
+ making this call. */
+# else /* FreeBSD, NetBSD >= 10, IRIX, Cygwin >= 2.5 */
+ /* On Linux, FreeBSD, NetBSD, IRIX,
+ acl_get_file (name, ACL_TYPE_ACCESS)
+ and acl_get_file (name, ACL_TYPE_DEFAULT) on a directory
+ either both succeed or both fail; it depends on the
+ file system. Therefore there is no point in making the second
+ call if the first one already failed. */
+ if (ret == 0
+ && (d_type == DT_DIR
+ || (d_type == DT_UNKNOWN && !(flags & _GL_DT_NOTDIR))))
+ {
+ acl = acl_get_file_or_link (name, ACL_TYPE_DEFAULT);
+ if (acl)
+ {
+# ifdef __CYGWIN__ /* Cygwin >= 2.5 */
+ ret = acl_access_nontrivial (acl);
+ saved_errno = errno;
+ acl_free (acl);
+ errno = saved_errno;
+# else
+ ret = (0 < acl_entries (acl));
+ acl_free (acl);
+# endif
+ }
+ else
+ {
+ ret = -1;
+# ifdef __CYGWIN__ /* Cygwin >= 2.5 */
+ if (d_type == DT_UNKNOWN)
+ ret = 0;
+# endif
+ }
+ }
# endif
- }
- else
- ret = -1;
- }
+ }
+ else
+ ret = -1;
# endif
- }
- else
- ret = -1;
-# endif
- }
- if (ret < 0)
- return - acl_errno_valid (errno);
- return ret;
-# elif HAVE_FACL && defined GETACL /* Solaris, Cygwin < 2.5, not HP-UX */
+ return ret < 0 ? - acl_errno_valid (errno) : ret;
+ }
+
+# else /* !HAVE_ACL_GET_FILE */
-# if defined ACL_NO_TRIVIAL
+ /* The remaining APIs always follow symlinks and operate on
+ platforms where symlinks do not have ACLs, so skip the APIs if
+ NAME is known to be a symlink. */
+ if (d_type != DT_LNK)
+ {
+
+# if HAVE_FACL && defined GETACL /* Solaris, Cygwin < 2.5, not HP-UX */
+
+# ifdef ACL_NO_TRIVIAL
/* Solaris 10 (newer version), which has additional API declared in
<sys/acl.h> (acl_t) and implemented in libsec (acl_set, acl_trivial,
acl_fromtext, ...). */
return acl_trivial (name);
-# else /* Solaris, Cygwin, general case */
+# else /* Solaris, Cygwin, general case */
/* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions
of Unixware. The acl() call returns the access and default ACL both
@@ -374,10 +539,7 @@ file_has_acl (char const *name, struct stat const *sb)
entries = malloced =
(aclent_t *) malloc (alloc * sizeof (aclent_t));
if (entries == NULL)
- {
- errno = ENOMEM;
- return -1;
- }
+ return -1;
continue;
}
break;
@@ -415,7 +577,7 @@ file_has_acl (char const *name, struct stat const *sb)
free (malloced);
}
-# ifdef ACE_GETACL
+# ifdef ACE_GETACL
/* Solaris also has a different variant of ACLs, used in ZFS and NFSv4
file systems (whereas the other ones are used in UFS file systems). */
{
@@ -447,10 +609,7 @@ file_has_acl (char const *name, struct stat const *sb)
alloc = 2 * alloc; /* <= alloc_max */
entries = malloced = (ace_t *) malloc (alloc * sizeof (ace_t));
if (entries == NULL)
- {
- errno = ENOMEM;
- return -1;
- }
+ return -1;
continue;
}
break;
@@ -491,12 +650,12 @@ file_has_acl (char const *name, struct stat const *sb)
}
free (malloced);
}
-# endif
+# endif
return 0;
-# endif
+# endif
-# elif HAVE_GETACL /* HP-UX */
+# elif HAVE_GETACL /* HP-UX */
{
struct acl_entry entries[NACLENTRIES];
@@ -539,7 +698,7 @@ file_has_acl (char const *name, struct stat const *sb)
}
}
-# if HAVE_ACLV_H /* HP-UX >= 11.11 */
+# if HAVE_ACLV_H /* HP-UX >= 11.11 */
{
struct acl entries[NACLVENTRIES];
@@ -574,9 +733,9 @@ file_has_acl (char const *name, struct stat const *sb)
}
}
-# endif
+# endif
-# elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */
+# elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */
acl_type_t type;
char aclbuf[1024];
@@ -604,10 +763,7 @@ file_has_acl (char const *name, struct stat const *sb)
free (acl);
acl = malloc (aclsize);
if (acl == NULL)
- {
- errno = ENOMEM;
- return -1;
- }
+ return -1;
}
if (type.u64 == ACL_AIXC)
@@ -634,7 +790,7 @@ file_has_acl (char const *name, struct stat const *sb)
return -1;
}
-# elif HAVE_STATACL /* older AIX */
+# elif HAVE_STATACL /* older AIX */
union { struct acl a; char room[4096]; } u;
@@ -643,7 +799,7 @@ file_has_acl (char const *name, struct stat const *sb)
return acl_nontrivial (&u.a);
-# elif HAVE_ACLSORT /* NonStop Kernel */
+# elif HAVE_ACLSORT /* NonStop Kernel */
{
struct acl entries[NACLENTRIES];
@@ -675,10 +831,29 @@ file_has_acl (char const *name, struct stat const *sb)
return acl_nontrivial (count, entries);
}
}
-
-# endif
+# endif
}
+# endif
+# endif
#endif
return 0;
}
+
+/* Return 1 if 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.
+ SB must be set to the stat buffer of NAME,
+ obtained through stat() or lstat(). */
+int
+file_has_acl (char const *name, struct stat const *sb)
+{
+ int flags = IFTODT (sb->st_mode);
+ if (!S_ISDIR (sb->st_mode))
+ flags |= _GL_DT_NOTDIR;
+ struct aclinfo ai;
+ int r = file_has_aclinfo (name, &ai, flags);
+ aclinfo_free (&ai);
+ return r;
+}
diff --git a/lib/getopt-cdefs.in.h b/lib/getopt-cdefs.in.h
index a1d304d49e8..9d704a9f6e5 100644
--- a/lib/getopt-cdefs.in.h
+++ b/lib/getopt-cdefs.in.h
@@ -46,10 +46,14 @@
# endif
#endif
+#if defined __clang__
+ /* clang really only groks GNU C 4.2, regardless of its value of __GNUC__. */
+# undef __GNUC_PREREQ
+# define __GNUC_PREREQ(maj, min) ((maj) < 4 + ((min) <= 2))
+#endif
#ifndef __GNUC_PREREQ
-# if defined __GNUC__ && defined __GNUC_VERSION__
-# define __GNUC_PREREQ(maj, min) \
- ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+# if defined __GNUC__ && defined __GNUC_MINOR__
+# define __GNUC_PREREQ(maj, min) ((maj) < __GNUC__ + ((min) <= __GNUC_MINOR__))
# else
# define __GNUC_PREREQ(maj, min) 0
# endif
diff --git a/lib/getopt-pfx-core.h b/lib/getopt-pfx-core.h
index 78b7816aa42..df2cb183a52 100644
--- a/lib/getopt-pfx-core.h
+++ b/lib/getopt-pfx-core.h
@@ -31,6 +31,13 @@
functions and variables. Renaming avoids problems with some
compilers and linkers. */
#ifdef __GETOPT_PREFIX
+
+/* Include platform-dependent header files that may declare getopt() and
+ friends. */
+# if defined _AIX || defined __hpux || defined __sun || defined __QNX__
+# include <stdio.h>
+# endif
+
# ifndef __GETOPT_ID
# define __GETOPT_CONCAT(x, y) x ## y
# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y)
diff --git a/lib/getopt.c b/lib/getopt.c
index ea2d1a529c4..47800c1b35b 100644
--- a/lib/getopt.c
+++ b/lib/getopt.c
@@ -42,7 +42,7 @@
# define funlockfile(fp) _IO_funlockfile (fp)
#else
# include "gettext.h"
-# define _(msgid) gettext (msgid)
+# define _(msgid) dgettext ("gnulib", msgid)
/* When used standalone, flockfile and funlockfile might not be
available. */
# if (!defined _POSIX_THREAD_SAFE_FUNCTIONS \
@@ -732,7 +732,7 @@ _getopt_internal (int argc, char **argv, const char *optstring,
NAME (int argc, char *const *argv, const char *optstring) \
{ \
return _getopt_internal (argc, (char **)argv, optstring, \
- 0, 0, 0, POSIXLY_CORRECT); \
+ NULL, NULL, 0, POSIXLY_CORRECT); \
}
#ifdef _LIBC
diff --git a/lib/gettext.h b/lib/gettext.h
index 39d5ae4daa5..bf0aa41e230 100644
--- a/lib/gettext.h
+++ b/lib/gettext.h
@@ -1,6 +1,5 @@
/* Convenience header for conditional use of GNU <libintl.h>.
- Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2024 Free Software
- Foundation, Inc.
+ 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
@@ -18,6 +17,7 @@
#ifndef _LIBGETTEXT_H
#define _LIBGETTEXT_H 1
+
/* NLS can be disabled through the configure --disable-nls option
or through "#define ENABLE NLS 0" before including this file. */
#if defined ENABLE_NLS && ENABLE_NLS
@@ -45,19 +45,19 @@
as well because people using "gettext.h" will not include <libintl.h>,
and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
is OK. */
-#if defined(__sun)
-# include <locale.h>
-#endif
+# if defined(__sun)
+# include <locale.h>
+# endif
/* Many header files from the libstdc++ coming with g++ 3.3 or newer include
<libintl.h>, which chokes if dcgettext is defined as a macro. So include
it now, to make later inclusions of <libintl.h> a NOP. */
-#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
-# include <cstdlib>
-# if (__GLIBC__ >= 2 && !defined __UCLIBC__) || _GLIBCXX_HAVE_LIBINTL_H
-# include <libintl.h>
+# if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
+# include <cstdlib>
+# if (__GLIBC__ >= 2 && !defined __UCLIBC__) || _GLIBCXX_HAVE_LIBINTL_H
+# include <libintl.h>
+# endif
# endif
-#endif
/* Disabled NLS.
The casts to 'const char *' serve the purpose of producing warnings
@@ -93,12 +93,14 @@
#endif
+
/* Prefer gnulib's setlocale override over libintl's setlocale override. */
#ifdef GNULIB_defined_setlocale
# undef setlocale
# define setlocale rpl_setlocale
#endif
+
/* A pseudo function call that serves as a marker for the automated
extraction of messages, but does not call gettext(). The run-time
translation is done at a different place in the code.
@@ -108,6 +110,7 @@
initializer for static 'char[]' or 'const char[]' variables. */
#define gettext_noop(String) String
+
/* The separator between msgctxt and msgid in a .mo file. */
#define GETTEXT_CONTEXT_GLUE "\004"
@@ -115,6 +118,9 @@
MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be
short and rarely need to change.
The letter 'p' stands for 'particular' or 'special'. */
+
+#include <locale.h> /* for LC_MESSAGES */
+
#ifdef DEFAULT_TEXT_DOMAIN
# define pgettext(Msgctxt, Msgid) \
pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
@@ -178,11 +184,12 @@ npgettext_aux (const char *domain,
return translation;
}
+
/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID
can be arbitrary expressions. But for string literals these macros are
less efficient than those above. */
-#include <string.h>
+#include <string.h> /* for memcpy */
/* GNULIB_NO_VLA can be defined to disable use of VLAs even if supported.
This relates to the -Wvla and -Wvla-larger-than warnings, enabled in
@@ -199,7 +206,7 @@ npgettext_aux (const char *domain,
#endif
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
-#include <stdlib.h>
+# include <stdlib.h> /* for malloc, free */
#endif
#define pgettext_expr(Msgctxt, Msgid) \
@@ -297,4 +304,5 @@ dcnpgettext_expr (const char *domain,
return (n == 1 ? msgid : msgid_plural);
}
+
#endif /* _LIBGETTEXT_H */
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index 5e541d9af1f..53275a4e62f 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -42,6 +42,7 @@
# --avoid=dup \
# --avoid=fchdir \
# --avoid=fstat \
+# --avoid=gnulib-i18n \
# --avoid=iswblank \
# --avoid=iswctype \
# --avoid=iswdigit \
@@ -80,6 +81,7 @@
# alloca-opt \
# binary-io \
# boot-time \
+# builtin-expect \
# byteswap \
# c-ctype \
# c-strcase \
@@ -261,7 +263,6 @@ DYNLIB_OBJ = @DYNLIB_OBJ@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
-EGREP = @EGREP@
EMACSRES = @EMACSRES@
EMACS_MANIFEST = @EMACS_MANIFEST@
EMULTIHOP_HIDDEN = @EMULTIHOP_HIDDEN@
@@ -336,6 +337,7 @@ GL_COND_OBJ_PTHREAD_SIGMASK_CONDITION = @GL_COND_OBJ_PTHREAD_SIGMASK_CONDITION@
GL_COND_OBJ_RAWMEMCHR_CONDITION = @GL_COND_OBJ_RAWMEMCHR_CONDITION@
GL_COND_OBJ_READLINKAT_CONDITION = @GL_COND_OBJ_READLINKAT_CONDITION@
GL_COND_OBJ_READLINK_CONDITION = @GL_COND_OBJ_READLINK_CONDITION@
+GL_COND_OBJ_REALLOC_POSIX_CONDITION = @GL_COND_OBJ_REALLOC_POSIX_CONDITION@
GL_COND_OBJ_REGEX_CONDITION = @GL_COND_OBJ_REGEX_CONDITION@
GL_COND_OBJ_SIG2STR_CONDITION = @GL_COND_OBJ_SIG2STR_CONDITION@
GL_COND_OBJ_SIGDESCR_NP_CONDITION = @GL_COND_OBJ_SIGDESCR_NP_CONDITION@
@@ -584,7 +586,6 @@ GL_GNULIB_READDIR = @GL_GNULIB_READDIR@
GL_GNULIB_READLINK = @GL_GNULIB_READLINK@
GL_GNULIB_READLINKAT = @GL_GNULIB_READLINKAT@
GL_GNULIB_REALLOCARRAY = @GL_GNULIB_REALLOCARRAY@
-GL_GNULIB_REALLOC_GNU = @GL_GNULIB_REALLOC_GNU@
GL_GNULIB_REALLOC_POSIX = @GL_GNULIB_REALLOC_POSIX@
GL_GNULIB_REALPATH = @GL_GNULIB_REALPATH@
GL_GNULIB_REMOVE = @GL_GNULIB_REMOVE@
@@ -707,7 +708,6 @@ GNUSTEP_CFLAGS = @GNUSTEP_CFLAGS@
GNU_OBJC_CFLAGS = @GNU_OBJC_CFLAGS@
GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
GOBJECT_LIBS = @GOBJECT_LIBS@
-GREP = @GREP@
GSETTINGS_CFLAGS = @GSETTINGS_CFLAGS@
GSETTINGS_LIBS = @GSETTINGS_LIBS@
GTK_CFLAGS = @GTK_CFLAGS@
@@ -1031,6 +1031,7 @@ LIB_MATH = @LIB_MATH@
LIB_NANOSLEEP = @LIB_NANOSLEEP@
LIB_PTHREAD = @LIB_PTHREAD@
LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@
+LIB_SELINUX = @LIB_SELINUX@
LIB_TIMER_TIME = @LIB_TIMER_TIME@
LIB_WSOCK32 = @LIB_WSOCK32@
LIB_XATTR = @LIB_XATTR@
@@ -1277,7 +1278,6 @@ REPLACE_READDIR = @REPLACE_READDIR@
REPLACE_READLINK = @REPLACE_READLINK@
REPLACE_READLINKAT = @REPLACE_READLINKAT@
REPLACE_REALLOCARRAY = @REPLACE_REALLOCARRAY@
-REPLACE_REALLOC_FOR_REALLOC_GNU = @REPLACE_REALLOC_FOR_REALLOC_GNU@
REPLACE_REALLOC_FOR_REALLOC_POSIX = @REPLACE_REALLOC_FOR_REALLOC_POSIX@
REPLACE_REALPATH = @REPLACE_REALPATH@
REPLACE_REMOVE = @REPLACE_REMOVE@
@@ -1384,6 +1384,7 @@ UNISTD_H_HAVE_SYS_RANDOM_H = @UNISTD_H_HAVE_SYS_RANDOM_H@
UNISTD_H_HAVE_WINSOCK2_H = @UNISTD_H_HAVE_WINSOCK2_H@
UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS = @UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@
USE_ACL = @USE_ACL@
+USE_SELINUX_SELINUX_H = @USE_SELINUX_SELINUX_H@
USE_STARTUP_NOTIFICATION = @USE_STARTUP_NOTIFICATION@
VMLIMIT_OBJ = @VMLIMIT_OBJ@
W32_LIBS = @W32_LIBS@
@@ -1470,16 +1471,13 @@ gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b_CONDITION = @gl_GNULIB_ENABLE
gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31_CONDITION = @gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31_CONDITION@
gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c_CONDITION = @gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c_CONDITION@
gl_GNULIB_ENABLED_61bcaca76b3e6f9ae55d57a1c3193bc4_CONDITION = @gl_GNULIB_ENABLED_61bcaca76b3e6f9ae55d57a1c3193bc4_CONDITION@
-gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec_CONDITION = @gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec_CONDITION@
gl_GNULIB_ENABLED_8444034ea779b88768865bb60b4fb8c9_CONDITION = @gl_GNULIB_ENABLED_8444034ea779b88768865bb60b4fb8c9_CONDITION@
gl_GNULIB_ENABLED_925677f0343de64b89a9f0c790b4104c_CONDITION = @gl_GNULIB_ENABLED_925677f0343de64b89a9f0c790b4104c_CONDITION@
gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1_CONDITION = @gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1_CONDITION@
gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36_CONDITION = @gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36_CONDITION@
gl_GNULIB_ENABLED_cloexec_CONDITION = @gl_GNULIB_ENABLED_cloexec_CONDITION@
-gl_GNULIB_ENABLED_d3b2383720ee0e541357aa2aac598e2b_CONDITION = @gl_GNULIB_ENABLED_d3b2383720ee0e541357aa2aac598e2b_CONDITION@
gl_GNULIB_ENABLED_dirfd_CONDITION = @gl_GNULIB_ENABLED_dirfd_CONDITION@
gl_GNULIB_ENABLED_e80bf6f757095d2e5fc94dafb8f8fc8b_CONDITION = @gl_GNULIB_ENABLED_e80bf6f757095d2e5fc94dafb8f8fc8b_CONDITION@
-gl_GNULIB_ENABLED_ef455225c00f5049c808c2eda3e76866_CONDITION = @gl_GNULIB_ENABLED_ef455225c00f5049c808c2eda3e76866_CONDITION@
gl_GNULIB_ENABLED_endian_CONDITION = @gl_GNULIB_ENABLED_endian_CONDITION@
gl_GNULIB_ENABLED_euidaccess_CONDITION = @gl_GNULIB_ENABLED_euidaccess_CONDITION@
gl_GNULIB_ENABLED_fd38c7e463b54744b77b98aeafb4fa7c_CONDITION = @gl_GNULIB_ENABLED_fd38c7e463b54744b77b98aeafb4fa7c_CONDITION@
@@ -2694,9 +2692,7 @@ endif
## begin gnulib module malloc-posix
ifeq (,$(OMIT_GNULIB_MODULE_malloc-posix))
-ifneq (,$(gl_GNULIB_ENABLED_ef455225c00f5049c808c2eda3e76866_CONDITION))
-endif
EXTRA_DIST += malloc.c
EXTRA_libgnu_a_SOURCES += malloc.c
@@ -2925,30 +2921,16 @@ EXTRA_libgnu_a_SOURCES += at-func.c
endif
## end gnulib module readlinkat
-## begin gnulib module realloc-gnu
-ifeq (,$(OMIT_GNULIB_MODULE_realloc-gnu))
-
-ifneq (,$(gl_GNULIB_ENABLED_d3b2383720ee0e541357aa2aac598e2b_CONDITION))
-
-endif
-EXTRA_DIST += realloc.c
-
-EXTRA_libgnu_a_SOURCES += realloc.c
-
-endif
-## end gnulib module realloc-gnu
-
## begin gnulib module realloc-posix
ifeq (,$(OMIT_GNULIB_MODULE_realloc-posix))
ifneq (,$(gl_GNULIB_ENABLED_61bcaca76b3e6f9ae55d57a1c3193bc4_CONDITION))
-
+ifneq (,$(GL_COND_OBJ_REALLOC_POSIX_CONDITION))
+libgnu_a_SOURCES += realloc.c
endif
-EXTRA_DIST += realloc.c
-
-EXTRA_libgnu_a_SOURCES += realloc.c
endif
+endif
## end gnulib module realloc-posix
## begin gnulib module regex
@@ -3459,9 +3441,8 @@ endif
ifeq (,$(OMIT_GNULIB_MODULE_stdlib))
BUILT_SOURCES += stdlib.h
+libgnu_a_SOURCES += stdlib.c
-# We need the following in order to create <stdlib.h> when the system
-# doesn't have one that works with the given compiler.
stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
$(_NORETURN_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
$(gl_V_at)$(SED_HEADER_STDOUT) \
@@ -3500,7 +3481,6 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-e 's/@''GNULIB_RAND''@/$(GL_GNULIB_RAND)/g' \
-e 's/@''GNULIB_RANDOM''@/$(GL_GNULIB_RANDOM)/g' \
-e 's/@''GNULIB_RANDOM_R''@/$(GL_GNULIB_RANDOM_R)/g' \
- -e 's/@''GNULIB_REALLOC_GNU''@/$(GL_GNULIB_REALLOC_GNU)/g' \
-e 's/@''GNULIB_REALLOC_POSIX''@/$(GL_GNULIB_REALLOC_POSIX)/g' \
-e 's/@''GNULIB_REALLOCARRAY''@/$(GL_GNULIB_REALLOCARRAY)/g' \
-e 's/@''GNULIB_REALPATH''@/$(GL_GNULIB_REALPATH)/g' \
@@ -3602,7 +3582,6 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-e 's|@''REPLACE_RAND''@|$(REPLACE_RAND)|g' \
-e 's|@''REPLACE_RANDOM''@|$(REPLACE_RANDOM)|g' \
-e 's|@''REPLACE_RANDOM_R''@|$(REPLACE_RANDOM_R)|g' \
- -e 's|@''REPLACE_REALLOC_FOR_REALLOC_GNU''@|$(REPLACE_REALLOC_FOR_REALLOC_GNU)|g' \
-e 's|@''REPLACE_REALLOC_FOR_REALLOC_POSIX''@|$(REPLACE_REALLOC_FOR_REALLOC_POSIX)|g' \
-e 's|@''REPLACE_REALLOCARRAY''@|$(REPLACE_REALLOCARRAY)|g' \
-e 's|@''REPLACE_REALPATH''@|$(REPLACE_REALPATH)|g' \
@@ -4446,17 +4425,6 @@ EXTRA_DIST += vla.h
endif
## end gnulib module vla
-## begin gnulib module xalloc-oversized
-ifeq (,$(OMIT_GNULIB_MODULE_xalloc-oversized))
-
-ifneq (,$(gl_GNULIB_ENABLED_682e609604ccaac6be382e4ee3a4eaec_CONDITION))
-
-endif
-EXTRA_DIST += xalloc-oversized.h
-
-endif
-## end gnulib module xalloc-oversized
-
mostlyclean-local: mostlyclean-generic
@for dir in '' $(MOSTLYCLEANDIRS); do \
diff --git a/lib/malloc.c b/lib/malloc.c
index 2a7867a1d1f..045ff82c1a7 100644
--- a/lib/malloc.c
+++ b/lib/malloc.c
@@ -17,28 +17,33 @@
/* written by Jim Meyering and Bruno Haible */
+/* Ensure that we call the system's malloc() below. */
#define _GL_USE_STDLIB_ALLOC 1
#include <config.h>
#include <stdlib.h>
#include <errno.h>
-
-#include "xalloc-oversized.h"
+#include <stdckdint.h>
/* Allocate an N-byte block of memory from the heap, even if N is 0. */
void *
rpl_malloc (size_t n)
{
+#if !HAVE_MALLOC_0_NONNULL
if (n == 0)
n = 1;
+#endif
- if (xalloc_oversized (n, 1))
+#if !HAVE_MALLOC_PTRDIFF
+ ptrdiff_t signed_n;
+ if (ckd_add (&signed_n, n, 0))
{
errno = ENOMEM;
return NULL;
}
+#endif
void *result = malloc (n);
diff --git a/lib/md5-stream.c b/lib/md5-stream.c
index fdd2bd8b4bf..2cbdda6b0fa 100644
--- a/lib/md5-stream.c
+++ b/lib/md5-stream.c
@@ -22,9 +22,6 @@
#include <config.h>
/* Specification. */
-#if HAVE_OPENSSL_MD5
-# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE
-#endif
#include "md5.h"
#include <stdlib.h>
diff --git a/lib/md5.h b/lib/md5.h
index 2f470703f5c..94cc6994cc1 100644
--- a/lib/md5.h
+++ b/lib/md5.h
@@ -52,10 +52,14 @@
#define MD5_DIGEST_SIZE 16
#define MD5_BLOCK_SIZE 64
+#if defined __clang__
+ /* clang really only groks GNU C 4.2, regardless of its value of __GNUC__. */
+# undef __GNUC_PREREQ
+# define __GNUC_PREREQ(maj, min) ((maj) < 4 + ((min) <= 2))
+#endif
#ifndef __GNUC_PREREQ
# if defined __GNUC__ && defined __GNUC_MINOR__
-# define __GNUC_PREREQ(maj, min) \
- ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+# define __GNUC_PREREQ(maj, min) ((maj) < __GNUC__ + ((min) <= __GNUC_MINOR__))
# else
# define __GNUC_PREREQ(maj, min) 0
# endif
diff --git a/lib/memset_explicit.c b/lib/memset_explicit.c
index 33c09873482..a5d2b00b7ea 100644
--- a/lib/memset_explicit.c
+++ b/lib/memset_explicit.c
@@ -27,7 +27,10 @@ memset_explicit (void *s, int c, size_t len)
#if HAVE_EXPLICIT_MEMSET
return explicit_memset (s, c, len);
#elif HAVE_MEMSET_S
- (void) memset_s (s, len, c, len);
+# if !HAVE_MEMSET_S_SUPPORTS_ZERO
+ if (len > 0)
+# endif
+ (void) memset_s (s, len, c, len);
return s;
#elif defined __GNUC__ && !defined __clang__
memset (s, c, len);
diff --git a/lib/mini-gmp.c b/lib/mini-gmp.c
index c580a8fc025..c97dc7e6cfa 100644
--- a/lib/mini-gmp.c
+++ b/lib/mini-gmp.c
@@ -2706,6 +2706,66 @@ mpn_gcd_11 (mp_limb_t u, mp_limb_t v)
return u << shift;
}
+mp_size_t
+mpn_gcd (mp_ptr rp, mp_ptr up, mp_size_t un, mp_ptr vp, mp_size_t vn)
+{
+ assert (un >= vn);
+ assert (vn > 0);
+ assert (!GMP_MPN_OVERLAP_P (up, un, vp, vn));
+ assert (vp[vn-1] > 0);
+ assert ((up[0] | vp[0]) & 1);
+
+ if (un > vn)
+ mpn_div_qr (NULL, up, un, vp, vn);
+
+ un = mpn_normalized_size (up, vn);
+ if (un == 0)
+ {
+ mpn_copyi (rp, vp, vn);
+ return vn;
+ }
+
+ if (!(vp[0] & 1))
+ MPN_PTR_SWAP (up, un, vp, vn);
+
+ while (un > 1 || vn > 1)
+ {
+ int shift;
+ assert (vp[0] & 1);
+
+ while (up[0] == 0)
+ {
+ up++;
+ un--;
+ }
+ gmp_ctz (shift, up[0]);
+ if (shift > 0)
+ {
+ gmp_assert_nocarry (mpn_rshift(up, up, un, shift));
+ un -= (up[un-1] == 0);
+ }
+
+ if (un < vn)
+ MPN_PTR_SWAP (up, un, vp, vn);
+ else if (un == vn)
+ {
+ int c = mpn_cmp (up, vp, un);
+ if (c == 0)
+ {
+ mpn_copyi (rp, up, un);
+ return un;
+ }
+ else if (c < 0)
+ MP_PTR_SWAP (up, vp);
+ }
+
+ gmp_assert_nocarry (mpn_sub (up, up, un, vp, vn));
+ un = mpn_normalized_size (up, un);
+ }
+ rp[0] = mpn_gcd_11 (up[0], vp[0]);
+ return 1;
+}
+
unsigned long
mpz_gcd_ui (mpz_t g, const mpz_t u, unsigned long v)
{
@@ -2765,42 +2825,11 @@ mpz_gcd (mpz_t g, const mpz_t u, const mpz_t v)
if (tu->_mp_size < tv->_mp_size)
mpz_swap (tu, tv);
- mpz_tdiv_r (tu, tu, tv);
- if (tu->_mp_size == 0)
- {
- mpz_swap (g, tv);
- }
- else
- for (;;)
- {
- int c;
-
- mpz_make_odd (tu);
- c = mpz_cmp (tu, tv);
- if (c == 0)
- {
- mpz_swap (g, tu);
- break;
- }
- if (c < 0)
- mpz_swap (tu, tv);
+ tu->_mp_size = mpn_gcd (tu->_mp_d, tu->_mp_d, tu->_mp_size, tv->_mp_d, tv->_mp_size);
+ mpz_mul_2exp (g, tu, gz);
- if (tv->_mp_size == 1)
- {
- mp_limb_t *gp;
-
- mpz_tdiv_r (tu, tu, tv);
- gp = MPZ_REALLOC (g, 1); /* gp = mpz_limbs_modify (g, 1); */
- *gp = mpn_gcd_11 (tu->_mp_d[0], tv->_mp_d[0]);
-
- g->_mp_size = *gp != 0; /* mpz_limbs_finish (g, 1); */
- break;
- }
- mpz_sub (tu, tu, tv);
- }
mpz_clear (tu);
mpz_clear (tv);
- mpz_mul_2exp (g, g, gz);
}
void
diff --git a/lib/mini-gmp.h b/lib/mini-gmp.h
index 59c24cf5111..f28cb360ce1 100644
--- a/lib/mini-gmp.h
+++ b/lib/mini-gmp.h
@@ -105,6 +105,7 @@ void mpn_mul_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t);
void mpn_sqr (mp_ptr, mp_srcptr, mp_size_t);
int mpn_perfect_square_p (mp_srcptr, mp_size_t);
mp_size_t mpn_sqrtrem (mp_ptr, mp_ptr, mp_srcptr, mp_size_t);
+mp_size_t mpn_gcd (mp_ptr, mp_ptr, mp_size_t, mp_ptr, mp_size_t);
mp_limb_t mpn_lshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int);
mp_limb_t mpn_rshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int);
diff --git a/lib/mktime-internal.h b/lib/mktime-internal.h
index 0693aaf1402..3e2848c1210 100644
--- a/lib/mktime-internal.h
+++ b/lib/mktime-internal.h
@@ -71,9 +71,8 @@ typedef int mktime_offset_t;
#endif
/* Subroutine of mktime. Return the time_t representation of TP and
- normalize TP, given that a struct tm * maps to a time_t as performed
- by FUNC. Record next guess for localtime-gmtime offset in *OFFSET. */
-extern __time64_t __mktime_internal (struct tm *tp,
- struct tm *(*func) (__time64_t const *,
- struct tm *),
+ normalize TP, given that a struct tm * maps to a time_t. If
+ LOCAL, the mapping is performed by localtime_r, otherwise by gmtime_r.
+ Record next guess for localtime-gmtime offset in *OFFSET. */
+extern __time64_t __mktime_internal (struct tm *tp, bool local,
mktime_offset_t *offset) attribute_hidden;
diff --git a/lib/mktime.c b/lib/mktime.c
index c704f415740..81d58fd01a3 100644
--- a/lib/mktime.c
+++ b/lib/mktime.c
@@ -51,7 +51,6 @@
#include <string.h>
#include <intprops.h>
-#include <verify.h>
#ifndef NEED_MKTIME_INTERNAL
# define NEED_MKTIME_INTERNAL 0
@@ -119,12 +118,12 @@ my_tzset (void)
__time64_t values that mktime can generate even on platforms where
__time64_t is wider than the int components of struct tm. */
-#if INT_MAX <= LONG_MAX / 4 / 366 / 24 / 60 / 60
+# if INT_MAX <= LONG_MAX / 4 / 366 / 24 / 60 / 60
typedef long int long_int;
-#else
+# else
typedef long long int long_int;
-#endif
-verify (INT_MAX <= TYPE_MAXIMUM (long_int) / 4 / 366 / 24 / 60 / 60);
+# endif
+static_assert (INT_MAX <= TYPE_MAXIMUM (long_int) / 4 / 366 / 24 / 60 / 60);
/* Shift A right by B bits portably, by dividing A by 2**B and
truncating towards minus infinity. B should be in the range 0 <= B
@@ -155,9 +154,9 @@ static long_int const mktime_max
= (TYPE_MAXIMUM (long_int) < TYPE_MAXIMUM (__time64_t)
? TYPE_MAXIMUM (long_int) : TYPE_MAXIMUM (__time64_t));
-#define EPOCH_YEAR 1970
-#define TM_YEAR_BASE 1900
-verify (TM_YEAR_BASE % 100 == 0);
+# define EPOCH_YEAR 1970
+# define TM_YEAR_BASE 1900
+static_assert (TM_YEAR_BASE % 100 == 0);
/* Is YEAR + TM_YEAR_BASE a leap year? */
static bool
@@ -172,9 +171,9 @@ leapyear (long_int year)
}
/* How many days come before each month (0-12). */
-#ifndef _LIBC
+# ifndef _LIBC
static
-#endif
+# endif
const unsigned short int __mon_yday[2][13] =
{
/* Normal years. */
@@ -206,7 +205,7 @@ static long_int
ydhms_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1,
int year0, int yday0, int hour0, int min0, int sec0)
{
- verify (-1 / 2 == 0);
+ static_assert (-1 / 2 == 0);
/* Compute intervening leap days correctly even if year is negative.
Take care to avoid integer overflow here. */
@@ -251,29 +250,33 @@ tm_diff (long_int year, long_int yday, int hour, int min, int sec,
tp->tm_hour, tp->tm_min, tp->tm_sec);
}
-/* Use CONVERT to convert T to a struct tm value in *TM. T must be in
- range for __time64_t. Return TM if successful, NULL (setting errno) on
- failure. */
+/* Convert T to a struct tm value in *TM. Use localtime64_r if LOCAL,
+ otherwise gmtime64_r. T must be in range for __time64_t. Return
+ TM if successful, NULL (setting errno) on failure. */
static struct tm *
-convert_time (struct tm *(*convert) (const __time64_t *, struct tm *),
- long_int t, struct tm *tm)
+convert_time (long_int t, bool local, struct tm *tm)
{
__time64_t x = t;
- return convert (&x, tm);
+ if (local)
+ return __localtime64_r (&x, tm);
+ else
+ return __gmtime64_r (&x, tm);
}
+/* Call it __tzconvert to sync with other parts of glibc. */
+#define __tz_convert convert_time
-/* Use CONVERT to convert *T to a broken down time in *TP.
- If *T is out of range for conversion, adjust it so that
- it is the nearest in-range value and then convert that.
- A value is in range if it fits in both __time64_t and long_int.
- Return TP on success, NULL (setting errno) on failure. */
+/* Convert *T to a broken down time in *TP (as if by localtime if
+ LOCAL, otherwise as if by gmtime). If *T is out of range for
+ conversion, adjust it so that it is the nearest in-range value and
+ then convert that. A value is in range if it fits in both
+ __time64_t and long_int. Return TP on success, NULL (setting
+ errno) on failure. */
static struct tm *
-ranged_convert (struct tm *(*convert) (const __time64_t *, struct tm *),
- long_int *t, struct tm *tp)
+ranged_convert (bool local, long_int *t, struct tm *tp)
{
long_int t1 = (*t < mktime_min ? mktime_min
: *t <= mktime_max ? *t : mktime_max);
- struct tm *r = convert_time (convert, t1, tp);
+ struct tm *r = __tz_convert (t1, local, tp);
if (r)
{
*t = t1;
@@ -294,7 +297,7 @@ ranged_convert (struct tm *(*convert) (const __time64_t *, struct tm *),
long_int mid = long_int_avg (ok, bad);
if (mid == ok || mid == bad)
break;
- if (convert_time (convert, mid, tp))
+ if (__tz_convert (mid, local, tp))
ok = mid, oktm = *tp;
else if (errno != EOVERFLOW)
return NULL;
@@ -310,36 +313,45 @@ ranged_convert (struct tm *(*convert) (const __time64_t *, struct tm *),
}
-/* Convert *TP to a __time64_t value, inverting
- the monotonic and mostly-unit-linear conversion function CONVERT.
- Use *OFFSET to keep track of a guess at the offset of the result,
+/* Convert *TP to a __time64_t value. If LOCAL, the reverse mapping
+ is performed as if localtime, otherwise as if by gmtime. Use
+ *OFFSET to keep track of a guess at the offset of the result,
compared to what the result would be for UTC without leap seconds.
- If *OFFSET's guess is correct, only one CONVERT call is needed.
- If successful, set *TP to the canonicalized struct tm;
+ If *OFFSET's guess is correct, only one reverse mapping call is
+ needed. If successful, set *TP to the canonicalized struct tm;
otherwise leave *TP alone, return ((time_t) -1) and set errno.
This function is external because it is used also by timegm.c. */
__time64_t
-__mktime_internal (struct tm *tp,
- struct tm *(*convert) (const __time64_t *, struct tm *),
- mktime_offset_t *offset)
+__mktime_internal (struct tm *tp, bool local, mktime_offset_t *offset)
{
struct tm tm;
- /* The maximum number of probes (calls to CONVERT) should be enough
- to handle any combinations of time zone rule changes, solar time,
- leap seconds, and oscillations around a spring-forward gap.
- POSIX.1 prohibits leap seconds, but some hosts have them anyway. */
+ /* The maximum number of probes should be enough to handle any
+ combinations of time zone rule changes, solar time, leap seconds,
+ and oscillations around a spring-forward gap. POSIX.1 prohibits
+ leap seconds, but some hosts have them anyway. */
int remaining_probes = 6;
- /* Time requested. Copy it in case CONVERT modifies *TP; this can
- occur if TP is localtime's returned value and CONVERT is localtime. */
+#ifndef _LIBC
+ /* Gnulib mktime doesn't lock the tz state, so it may need to probe
+ more often if some other thread changes local time while
+ __mktime_internal is probing. Double the number of probes; this
+ should suffice for practical cases that are at all likely. */
+ remaining_probes *= 2;
+#endif
+
+ /* Time requested. Copy it in case gmtime/localtime modify *TP;
+ this can occur if TP is localtime's returned value and CONVERT is
+ localtime. */
int sec = tp->tm_sec;
int min = tp->tm_min;
int hour = tp->tm_hour;
int mday = tp->tm_mday;
int mon = tp->tm_mon;
int year_requested = tp->tm_year;
- int isdst = tp->tm_isdst;
+
+ /* Ignore any tm_isdst request for timegm. */
+ int isdst = local ? tp->tm_isdst : 0;
/* 1 if the previous probe was DST. */
int dst2 = 0;
@@ -390,7 +402,7 @@ __mktime_internal (struct tm *tp,
while (true)
{
- if (! ranged_convert (convert, &t, &tm))
+ if (! ranged_convert (local, &t, &tm))
return -1;
long_int dt = tm_diff (year, yday, hour, min, sec, &tm);
if (dt == 0)
@@ -469,7 +481,7 @@ __mktime_internal (struct tm *tp,
if (! ckd_add (&ot, t, delta * direction))
{
struct tm otm;
- if (! ranged_convert (convert, &ot, &otm))
+ if (! ranged_convert (local, &ot, &otm))
return -1;
if (! isdst_differ (isdst, otm.tm_isdst))
{
@@ -479,7 +491,7 @@ __mktime_internal (struct tm *tp,
&otm);
if (mktime_min <= gt && gt <= mktime_max)
{
- if (convert_time (convert, gt, &tm))
+ if (__tz_convert (gt, local, &tm))
{
t = gt;
goto offset_found;
@@ -493,7 +505,7 @@ __mktime_internal (struct tm *tp,
/* No unusual DST offset was found nearby. Assume one-hour DST. */
t += 60 * 60 * dst_difference;
- if (mktime_min <= t && t <= mktime_max && convert_time (convert, t, &tm))
+ if (mktime_min <= t && t <= mktime_max && __tz_convert (t, local, &tm))
goto offset_found;
__set_errno (EOVERFLOW);
@@ -520,7 +532,7 @@ __mktime_internal (struct tm *tp,
__set_errno (EOVERFLOW);
return -1;
}
- if (! convert_time (convert, t, &tm))
+ if (! __tz_convert (t, local, &tm))
return -1;
}
@@ -536,14 +548,13 @@ __mktime_internal (struct tm *tp,
__time64_t
__mktime64 (struct tm *tp)
{
- /* POSIX.1 8.1.1 requires that whenever mktime() is called, the
- time zone names contained in the external variable 'tzname' shall
- be set as if the tzset() function had been called. */
+ /* POSIX.1 requires mktime to set external variables like 'tzname'
+ as though tzset had been called. */
__tzset ();
# if defined _LIBC || NEED_MKTIME_WORKING
static mktime_offset_t localtime_offset;
- return __mktime_internal (tp, __localtime64_r, &localtime_offset);
+ return __mktime_internal (tp, true, &localtime_offset);
# else
# undef mktime
return mktime (tp);
diff --git a/lib/nproc.c b/lib/nproc.c
index 92a07e82890..0b5898d88ff 100644
--- a/lib/nproc.c
+++ b/lib/nproc.c
@@ -20,6 +20,7 @@
#include <config.h>
#include "nproc.h"
+#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
@@ -125,6 +126,46 @@ num_processors_via_affinity_mask (void)
}
}
#elif HAVE_SCHED_GETAFFINITY_LIKE_GLIBC /* glibc >= 2.3.4 */
+ /* There are two ways to use the sched_getaffinity() function:
+ - With a statically-sized cpu_set_t.
+ - With a dynamically-sized cpu_set_t.
+ Documentation:
+ <https://www.kernel.org/doc/man-pages/online/pages/man2/sched_getaffinity.2.html>
+ <https://www.kernel.org/doc/man-pages/online/pages/man3/CPU_SET.3.html>
+ The second way has the advantage that it works on systems with more than
+ 1024 CPUs. The first way has the advantage that it works also when memory
+ is tight. */
+# if defined CPU_ALLOC_SIZE /* glibc >= 2.6 */
+ {
+ unsigned int alloc_count = 1024;
+ for (;;)
+ {
+ cpu_set_t *set = CPU_ALLOC (alloc_count);
+ if (set == NULL)
+ /* Out of memory. */
+ break;
+ unsigned int size = CPU_ALLOC_SIZE (alloc_count);
+ if (sched_getaffinity (0, size, set) == 0)
+ {
+ unsigned int count = CPU_COUNT_S (size, set);
+ CPU_FREE (set);
+ return count;
+ }
+ if (errno != EINVAL)
+ {
+ /* Some other error. */
+ CPU_FREE (set);
+ return 0;
+ }
+ CPU_FREE (set);
+ /* Retry with some larger cpu_set_t. */
+ alloc_count *= 2;
+ if (alloc_count == 0)
+ /* Integer overflow. Avoid an endless loop. */
+ return 0;
+ }
+ }
+# endif
{
cpu_set_t set;
diff --git a/lib/pipe2.c b/lib/pipe2.c
index 7b476df3457..e290f94a94a 100644
--- a/lib/pipe2.c
+++ b/lib/pipe2.c
@@ -40,7 +40,7 @@ pipe2 (int fd[2], int flags)
{
/* Mingw _pipe() corrupts fd on failure; also, if we succeed at
creating the pipe but later fail at changing fcntl, we want
- to leave fd unchanged: http://austingroupbugs.net/view.php?id=467 */
+ to leave fd unchanged: https://austingroupbugs.net/view.php?id=467 */
int tmp[2];
tmp[0] = fd[0];
tmp[1] = fd[1];
diff --git a/lib/realloc.c b/lib/realloc.c
index 0573139625e..58044745f45 100644
--- a/lib/realloc.c
+++ b/lib/realloc.c
@@ -18,17 +18,21 @@
/* written by Jim Meyering and Bruno Haible */
+/* Ensure that we call the system's realloc() below. */
+#define _GL_USE_STDLIB_ALLOC 1
#include <config.h>
+#define _GL_REALLOC_INLINE _GL_EXTERN_INLINE
#include <stdlib.h>
#include <errno.h>
+#include <stdckdint.h>
-#include "xalloc-oversized.h"
+#ifdef __CHERI_PURE_CAPABILITY__
+# include <cheri.h>
+#endif
-/* Call the system's realloc below. This file does not define
- _GL_USE_STDLIB_ALLOC because it needs Gnulib's malloc if present. */
-#undef realloc
+#ifndef _GL_INLINE_RPL_REALLOC
/* Change the size of an allocated block of memory P to N bytes,
with error checking. If P is NULL, use malloc. Otherwise if N is zero,
@@ -37,27 +41,70 @@
void *
rpl_realloc (void *p, size_t n)
{
- if (p == NULL)
- return malloc (n);
+ size_t n1 = n;
if (n == 0)
{
- free (p);
- return NULL;
+# if NEED_SANITIZED_REALLOC
+ /* When P is non-null, ISO C23 ยง7.24.3.7.(3) says realloc (P, 0) has
+ undefined behavior even though C17 and earlier partially defined
+ the behavior. Let the programmer know.
+ When the undefined-behaviour sanitizers report this case, i.e. when
+ <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117233> and
+ <https://github.com/llvm/llvm-project/issues/113065>
+ have been closed and new releases of GCC and clang have been made,
+ we can revisit this code. */
+ if (p != NULL)
+ abort ();
+# endif
+
+ /* realloc (NULL, 0) acts like glibc malloc (0), i.e., like malloc (1)
+ except the caller cannot dereference any non-null return.
+
+ realloc (P, 0) with non-null P is a messier situation.
+ As mentioned above, C23 says behavior is undefined.
+ POSIX.1-2024 extends C17 to say realloc (P, 0)
+ either fails by setting errno and returning a null pointer,
+ or succeeds by freeing P and then either:
+ (a) setting errno=EINVAL and returning a null pointer; or
+ (b) acting like a successful malloc (0).
+ glibc 1 through 2.1 realloc acted like (b),
+ which conforms to C17, to C23 and to POSIX.1-2024.
+ glibc 2.1.1+ realloc acts like (a) except it does not set errno;
+ this conforms to C17 and to C23 but not to POSIX.1-2024.
+ Quite possibly future versions of POSIX will change,
+ due either to C23 or to (a)'s semantics being messy.
+ Act like (b), as that's easy, matches GNU, BSD and V7 malloc,
+ matches BSD and V7 realloc, and requires no extra code at
+ caller sites. */
+
+# if !HAVE_REALLOC_0_NONNULL
+ n1 = 1;
+# endif
}
- if (xalloc_oversized (n, 1))
+# if !HAVE_MALLOC_PTRDIFF
+ ptrdiff_t signed_n;
+ if (ckd_add (&signed_n, n, 0))
{
errno = ENOMEM;
return NULL;
}
+# endif
- void *result = realloc (p, n);
+ void *result = realloc (p, n1);
-#if !HAVE_MALLOC_POSIX
+# if !HAVE_MALLOC_POSIX
if (result == NULL)
errno = ENOMEM;
-#endif
+# endif
+
+# ifdef __CHERI_PURE_CAPABILITY__
+ if (result != NULL)
+ result = cheri_bounds_set (result, n);
+# endif
return result;
}
+
+#endif
diff --git a/lib/regex.h b/lib/regex.h
index ccf40cebc0e..004dc624050 100644
--- a/lib/regex.h
+++ b/lib/regex.h
@@ -647,10 +647,12 @@ extern int re_exec (const char *);
|| 2 < __GNUC__ + (95 <= __GNUC_MINOR__) \
|| __clang_major__ >= 3
# define _Restrict_ __restrict
-# elif 199901L <= __STDC_VERSION__ || defined restrict
-# define _Restrict_ restrict
# else
-# define _Restrict_
+# if 199901L <= __STDC_VERSION__ || defined restrict
+# define _Restrict_ restrict
+# else
+# define _Restrict_
+# endif
# endif
#endif
/* For the ISO C99 syntax
@@ -661,13 +663,15 @@ extern int re_exec (const char *);
#ifndef _Restrict_arr_
# ifdef __restrict_arr
# define _Restrict_arr_ __restrict_arr
-# elif ((199901L <= __STDC_VERSION__ \
+# else
+# if ((199901L <= __STDC_VERSION__ \
|| 3 < __GNUC__ + (1 <= __GNUC_MINOR__) \
|| __clang_major__ >= 3) \
&& !defined __cplusplus)
-# define _Restrict_arr_ _Restrict_
-# else
-# define _Restrict_arr_
+# define _Restrict_arr_ _Restrict_
+# else
+# define _Restrict_arr_
+# endif
# endif
#endif
diff --git a/lib/regex_internal.c b/lib/regex_internal.c
index 8cd096ebcfb..6ccf701f266 100644
--- a/lib/regex_internal.c
+++ b/lib/regex_internal.c
@@ -937,8 +937,7 @@ re_node_set_alloc (re_node_set *set, Idx size)
set->alloc = size;
set->nelem = 0;
set->elems = re_malloc (Idx, size);
- if (__glibc_unlikely (set->elems == NULL)
- && (MALLOC_0_IS_NONNULL || size != 0))
+ if (__glibc_unlikely (set->elems == NULL))
return REG_ESPACE;
return REG_NOERROR;
}
diff --git a/lib/regex_internal.h b/lib/regex_internal.h
index 6165cb17c70..02c2ca68960 100644
--- a/lib/regex_internal.h
+++ b/lib/regex_internal.h
@@ -100,10 +100,12 @@
/* This is for other GNU distributions with internationalized messages. */
#if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC
# include <libintl.h>
+# undef gettext
# ifdef _LIBC
-# undef gettext
# define gettext(msgid) \
__dcgettext (_libc_intl_domainname, msgid, LC_MESSAGES)
+# else
+# define gettext(msgid) dgettext ("gnulib", msgid)
# endif
#else
# undef gettext
@@ -436,12 +438,6 @@ typedef struct re_dfa_t re_dfa_t;
#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx))
#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx))
-#ifdef _LIBC
-# define MALLOC_0_IS_NONNULL 1
-#elif !defined MALLOC_0_IS_NONNULL
-# define MALLOC_0_IS_NONNULL 0
-#endif
-
#ifndef MAX
# define MAX(a,b) ((a) < (b) ? (b) : (a))
#endif
diff --git a/lib/stdio-impl.h b/lib/stdio-impl.h
index 63ebf7c64b7..dfb5166171a 100644
--- a/lib/stdio-impl.h
+++ b/lib/stdio-impl.h
@@ -110,7 +110,7 @@
# endif
# if (defined __NetBSD__ && __NetBSD_Version__ >= 105270000) || defined __OpenBSD__ || defined __minix /* NetBSD >= 1.5ZA, OpenBSD, Minix 3 */
- /* See <http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup>
+ /* See <https://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup>
and <https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup>
and <https://github.com/Stichting-MINIX-Research-Foundation/minix/blob/master/lib/libc/stdio/fileext.h> */
struct __sfileext
diff --git a/lib/stdlib.c b/lib/stdlib.c
new file mode 100644
index 00000000000..521d64627dc
--- /dev/null
+++ b/lib/stdlib.c
@@ -0,0 +1,21 @@
+/* Inline functions for <stdlib.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/>. */
+
+#include <config.h>
+
+#define _GL_STDLIB_INLINE _GL_EXTERN_INLINE
+#include <stdlib.h>
diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h
index 6667f426ad9..adbef69131b 100644
--- a/lib/stdlib.in.h
+++ b/lib/stdlib.in.h
@@ -54,7 +54,7 @@
/* This file uses _Noreturn, _GL_ATTRIBUTE_DEALLOC, _GL_ATTRIBUTE_MALLOC,
_GL_ATTRIBUTE_NODISCARD, _GL_ATTRIBUTE_NOTHROW, _GL_ATTRIBUTE_PURE,
- GNULIB_POSIXCHECK, HAVE_RAW_DECL_*. */
+ _GL_INLINE_HEADER_BEGIN, GNULIB_POSIXCHECK, HAVE_RAW_DECL_*. */
#if !_GL_CONFIG_H_INCLUDED
#error "Please include config.h first."
#endif
@@ -130,6 +130,14 @@ struct random_data
# include <string>
#endif
+_GL_INLINE_HEADER_BEGIN
+#ifndef _GL_STDLIB_INLINE
+# define _GL_STDLIB_INLINE _GL_INLINE
+#endif
+#ifndef _GL_REALLOC_INLINE
+# define _GL_REALLOC_INLINE _GL_INLINE
+#endif
+
/* _GL_ATTRIBUTE_DEALLOC (F, I) declares that the function returns pointers
that can be freed by passing them as the Ith argument to the
function F. */
@@ -283,8 +291,8 @@ _GL_CXXALIASWARN (free);
#elif defined GNULIB_POSIXCHECK
# undef free
/* Assume free is always declared. */
-_GL_WARN_ON_USE (free, "free is not future POSIX compliant everywhere - "
- "use gnulib module free for portability");
+_GL_WARN_ON_USE (free, "free is not POSIX:2024 compliant everywhere - "
+ "use gnulib module free-posix for portability");
#endif
@@ -367,9 +375,10 @@ _GL_WARN_ON_USE (atoll, "atoll is unportable - "
#endif
#if @GNULIB_CALLOC_POSIX@
-# if (@GNULIB_CALLOC_POSIX@ && @REPLACE_CALLOC_FOR_CALLOC_POSIX@) \
+# if @REPLACE_CALLOC_FOR_CALLOC_POSIX@ \
|| (@GNULIB_CALLOC_GNU@ && @REPLACE_CALLOC_FOR_CALLOC_GNU@)
-# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# if !((defined __cplusplus && defined GNULIB_NAMESPACE) \
+ || _GL_USE_STDLIB_ALLOC)
# undef calloc
# define calloc rpl_calloc
# endif
@@ -681,7 +690,7 @@ _GL_WARN_ON_USE (grantpt, "grantpt is not portable - "
by never specifying a zero size), so it does not need malloc or
realloc to be redefined. */
#if @GNULIB_MALLOC_POSIX@
-# if (@GNULIB_MALLOC_POSIX@ && @REPLACE_MALLOC_FOR_MALLOC_POSIX@) \
+# if @REPLACE_MALLOC_FOR_MALLOC_POSIX@ \
|| (@GNULIB_MALLOC_GNU@ && @REPLACE_MALLOC_FOR_MALLOC_GNU@)
# if !((defined __cplusplus && defined GNULIB_NAMESPACE) \
|| _GL_USE_STDLIB_ALLOC)
@@ -740,11 +749,12 @@ _GL_WARN_ON_USE (malloc, "malloc is not POSIX compliant everywhere - "
/* Return maximum number of bytes of a multibyte character. */
#if @REPLACE_MB_CUR_MAX@
# if !GNULIB_defined_MB_CUR_MAX
-static inline
-int gl_MB_CUR_MAX (void)
+_GL_STDLIB_INLINE int
+gl_MB_CUR_MAX (void)
{
/* Turn the value 3 to the value 4, as needed for the UTF-8 encoding. */
- return MB_CUR_MAX + (MB_CUR_MAX == 3);
+ int gl_mb_cur_max = MB_CUR_MAX;
+ return gl_mb_cur_max == 3 ? 4 : gl_mb_cur_max;
}
# undef MB_CUR_MAX
# define MB_CUR_MAX gl_MB_CUR_MAX ()
@@ -1454,16 +1464,25 @@ _GL_WARN_ON_USE (setstate_r, "setstate_r is unportable - "
#if @GNULIB_REALLOC_POSIX@
-# if (@GNULIB_REALLOC_POSIX@ && @REPLACE_REALLOC_FOR_REALLOC_POSIX@) \
- || (@GNULIB_REALLOC_GNU@ && @REPLACE_REALLOC_FOR_REALLOC_GNU@)
+# if @REPLACE_REALLOC_FOR_REALLOC_POSIX@
+# if @REPLACE_REALLOC_FOR_REALLOC_POSIX@ == 2
+# define _GL_INLINE_RPL_REALLOC 1
+_GL_REALLOC_INLINE void *
+rpl_realloc (void *ptr, size_t size)
+{
+ return realloc (ptr, size ? size : 1);
+}
+# endif
# if !((defined __cplusplus && defined GNULIB_NAMESPACE) \
|| _GL_USE_STDLIB_ALLOC)
# undef realloc
# define realloc rpl_realloc
# endif
+# if !defined _GL_INLINE_RPL_REALLOC
_GL_FUNCDECL_RPL (realloc, void *,
(void *ptr, size_t size),
_GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_NODISCARD);
+# endif
_GL_CXXALIAS_RPL (realloc, void *, (void *ptr, size_t size));
# else
# if __GNUC__ >= 11 && !defined __clang__
@@ -1968,6 +1987,8 @@ _GL_CXXALIASWARN (wctomb);
#endif
+_GL_INLINE_HEADER_END
+
#endif /* _@GUARD_PREFIX@_STDLIB_H */
#endif /* _@GUARD_PREFIX@_STDLIB_H */
#endif
diff --git a/lib/timegm.c b/lib/timegm.c
index e5cf30c0198..ba28b3ecd96 100644
--- a/lib/timegm.c
+++ b/lib/timegm.c
@@ -30,8 +30,7 @@ __time64_t
__timegm64 (struct tm *tmp)
{
static mktime_offset_t gmtime_offset;
- tmp->tm_isdst = 0;
- return __mktime_internal (tmp, __gmtime64_r, &gmtime_offset);
+ return __mktime_internal (tmp, false, &gmtime_offset);
}
#if defined _LIBC && __TIMESIZE != 64
diff --git a/lib/unistd.in.h b/lib/unistd.in.h
index 20b1356fd38..ceb3cb48f15 100644
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -181,6 +181,9 @@ _GL_INLINE_HEADER_BEGIN
#ifndef _GL_UNISTD_INLINE
# define _GL_UNISTD_INLINE _GL_INLINE
#endif
+#ifndef _GL_GETPAGESIZE_INLINE
+# define _GL_GETPAGESIZE_INLINE _GL_INLINE
+#endif
/* Hide some function declarations from <winsock2.h>. */
@@ -1478,7 +1481,7 @@ _GL_FUNCDECL_SYS (getpagesize, int, (void), );
# define getpagesize() _gl_getpagesize ()
# else
# if !GNULIB_defined_getpagesize_function
-_GL_UNISTD_INLINE int
+_GL_GETPAGESIZE_INLINE int
getpagesize ()
{
return _gl_getpagesize ();
diff --git a/lib/utimens.c b/lib/utimens.c
index cd86a44ea76..3c81b5c3492 100644
--- a/lib/utimens.c
+++ b/lib/utimens.c
@@ -78,6 +78,21 @@ static int utimensat_works_really;
static int lutimensat_works_really;
#endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
+static bool
+is_valid_timespec (struct timespec const *timespec)
+{
+ return (timespec->tv_nsec == UTIME_NOW
+ || timespec->tv_nsec == UTIME_OMIT
+ || (0 <= timespec->tv_nsec && timespec->tv_nsec < TIMESPEC_HZ));
+}
+
+static bool
+is_valid_timespecs (struct timespec const timespec[2])
+{
+ return (is_valid_timespec (&timespec[0])
+ && is_valid_timespec (&timespec[1]));
+}
+
/* Validate the requested timestamps. Return 0 if the resulting
timespec can be used for utimensat (after possibly modifying it to
work around bugs in utimensat). Return a positive value if the
@@ -90,14 +105,7 @@ validate_timespec (struct timespec timespec[2])
{
int result = 0;
int utime_omit_count = 0;
- if ((timespec[0].tv_nsec != UTIME_NOW
- && timespec[0].tv_nsec != UTIME_OMIT
- && ! (0 <= timespec[0].tv_nsec
- && timespec[0].tv_nsec < TIMESPEC_HZ))
- || (timespec[1].tv_nsec != UTIME_NOW
- && timespec[1].tv_nsec != UTIME_OMIT
- && ! (0 <= timespec[1].tv_nsec
- && timespec[1].tv_nsec < TIMESPEC_HZ)))
+ if (!is_valid_timespecs (timespec))
{
errno = EINVAL;
return -1;
@@ -516,24 +524,44 @@ fdutimens (int fd, char const *file, struct timespec const timespec[2])
}
}
-#if !HAVE_UTIMENS
/* Set the access and modification timestamps of FILE to be
TIMESPEC[0] and TIMESPEC[1], respectively. */
int
utimens (char const *file, struct timespec const timespec[2])
+#undef utimens
{
+#if HAVE_UTIMENS
+ /* NetBSD's native utimens() does not fulfil the Gnulib expectations:
+ At least in NetBSD 10.0, it does not validate the timespec argument. */
+ if (timespec != NULL && !is_valid_timespecs (timespec))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ return utimens (file, timespec);
+#else
return fdutimens (-1, file, timespec);
-}
#endif
+}
-#if !HAVE_LUTIMENS
/* Set the access and modification timestamps of FILE to be
TIMESPEC[0] and TIMESPEC[1], respectively, without dereferencing
symlinks. Fail with ENOSYS if the platform does not support
changing symlink timestamps, but FILE was a symlink. */
int
lutimens (char const *file, struct timespec const timespec[2])
+#undef lutimens
{
+#if HAVE_LUTIMENS
+ /* NetBSD's native lutimens() does not fulfil the Gnulib expectations:
+ At least in NetBSD 10.0, it does not validate the timespec argument. */
+ if (timespec != NULL && !is_valid_timespecs (timespec))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ return lutimens (file, timespec);
+#else
struct timespec adjusted_timespec[2];
struct timespec *ts = timespec ? adjusted_timespec : NULL;
int adjustment_needed = 0;
@@ -553,11 +581,11 @@ lutimens (char const *file, struct timespec const timespec[2])
fdutimens' worry about buggy NFS clients. But we do have to
worry about bogus return values. */
-#if HAVE_UTIMENSAT
+# if HAVE_UTIMENSAT
if (0 <= lutimensat_works_really)
{
int result;
-# if defined __linux__ || defined __sun || defined __NetBSD__
+# if defined __linux__ || defined __sun || defined __NetBSD__
/* As recently as Linux kernel 2.6.32 (Dec 2009), several file
systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
but work if both times are either explicitly specified or
@@ -582,9 +610,9 @@ lutimens (char const *file, struct timespec const timespec[2])
/* Note that st is good, in case utimensat gives ENOSYS. */
adjustment_needed++;
}
-# endif
+# endif
result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW);
-# ifdef __linux__
+# ifdef __linux__
/* Work around a kernel bug:
https://bugzilla.redhat.com/show_bug.cgi?id=442352
https://bugzilla.redhat.com/show_bug.cgi?id=449910
@@ -594,7 +622,7 @@ lutimens (char const *file, struct timespec const timespec[2])
are no longer in common use. */
if (0 < result)
errno = ENOSYS;
-# endif
+# endif
if (result == 0 || errno != ENOSYS)
{
utimensat_works_really = 1;
@@ -603,7 +631,7 @@ lutimens (char const *file, struct timespec const timespec[2])
}
}
lutimensat_works_really = -1;
-#endif /* HAVE_UTIMENSAT */
+# endif /* HAVE_UTIMENSAT */
/* The platform lacks an interface to set file timestamps with
nanosecond resolution, so do the best we can, discarding any
@@ -619,7 +647,7 @@ lutimens (char const *file, struct timespec const timespec[2])
/* On Linux, lutimes is a thin wrapper around utimensat, so there is
no point trying lutimes if utimensat failed with ENOSYS. */
-#if HAVE_LUTIMES && !HAVE_UTIMENSAT
+# if HAVE_LUTIMES && !HAVE_UTIMENSAT
{
struct timeval timeval[2];
struct timeval *t;
@@ -639,7 +667,7 @@ lutimens (char const *file, struct timespec const timespec[2])
if (result == 0 || errno != ENOSYS)
return result;
}
-#endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */
+# endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */
/* Out of luck for symlinks, but we still handle regular files. */
if (!(adjustment_needed || REPLACE_FUNC_STAT_FILE) && lstat (file, &st))
@@ -648,5 +676,5 @@ lutimens (char const *file, struct timespec const timespec[2])
return fdutimens (-1, file, ts);
errno = ENOSYS;
return -1;
-}
#endif
+}
diff --git a/lib/utimens.h b/lib/utimens.h
index e85477b8493..762c3f9a858 100644
--- a/lib/utimens.h
+++ b/lib/utimens.h
@@ -33,12 +33,16 @@ extern "C" {
#endif
int fdutimens (int, char const *, struct timespec const [2]);
-#if !HAVE_UTIMENS
+
+#if HAVE_UTIMENS
+# define utimens rpl_utimens
+#endif
int utimens (char const *, struct timespec const [2]);
+
+#if HAVE_LUTIMENS
+# define lutimens rpl_lutimens
#endif
-#if !HAVE_LUTIMENS
int lutimens (char const *, struct timespec const [2]);
-#endif
#ifdef __cplusplus
}