summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2025-01-15 19:31:07 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2025-01-15 19:31:39 -0800
commit74dc2bd28007e68532d9813a57d3ec7da0c390e3 (patch)
tree1dbf3c1106bfe8b240165710e73c18f3f1940f89 /lib
parent4f946a652278cc72a777fe56999bc4525f53e03a (diff)
Update from Gnulib by running admin/merge-gnulib
Diffstat (limited to 'lib')
-rw-r--r--lib/fcntl.in.h6
-rw-r--r--lib/file-has-acl.c46
-rw-r--r--lib/gnulib.mk.in8
-rw-r--r--lib/mktime-internal.h7
-rw-r--r--lib/mktime.c70
-rw-r--r--lib/stdlib.in.h5
-rw-r--r--lib/string.in.h36
-rw-r--r--lib/sys_select.in.h8
8 files changed, 136 insertions, 50 deletions
diff --git a/lib/fcntl.in.h b/lib/fcntl.in.h
index 5f06c4fe10f..ac61c0865a4 100644
--- a/lib/fcntl.in.h
+++ b/lib/fcntl.in.h
@@ -369,8 +369,12 @@ _GL_WARN_ON_USE (openat, "openat is not portable - "
# define O_RSYNC 0
#endif
+#if defined O_SEARCH && defined O_PATH && O_SEARCH == O_PATH
+# undef O_SEARCH /* musl mistakenly #defines O_SEARCH to O_PATH. */
+#endif
+
#ifndef O_SEARCH
-# define O_SEARCH O_RDONLY /* This is often close enough in older systems. */
+# define O_SEARCH O_RDONLY /* Often close enough in non-POSIX systems. */
#endif
#ifndef O_SYNC
diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c
index 35dcc19f169..e8413f8f85f 100644
--- a/lib/file-has-acl.c
+++ b/lib/file-has-acl.c
@@ -99,6 +99,36 @@ enum {
ACE4_IDENTIFIER_GROUP = 0x00000040
};
+/* AI indicates XATTR may be present but wasn't accessible.
+ This is the case when [l]listxattr failed with E2BIG,
+ or failed with EACCES which in Linux kernel 6.12 NFS can mean merely
+ that we lack read access.
+*/
+
+static bool
+aclinfo_may_indicate_xattr (struct aclinfo const *ai)
+{
+ return ai->size < 0 && (ai->u.err == EACCES || ai->u.err == E2BIG);
+}
+
+/* Does NAME have XATTR? */
+
+static bool
+has_xattr (char const *xattr, struct aclinfo const *ai,
+ MAYBE_UNUSED char const *restrict name, MAYBE_UNUSED 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));
+ if (0 <= ret || (errno == ERANGE || errno == E2BIG))
+ return true;
+ }
+ return false;
+}
+
/* Does AI's xattr set contain XATTR? */
bool
@@ -176,11 +206,13 @@ get_aclinfo (char const *name, struct aclinfo *ai, int flags)
}
}
- if (0 < ai->size && flags & ACL_GET_SCONTEXT)
+ /* A security context can exist only if extended attributes do. */
+ if (flags & ACL_GET_SCONTEXT
+ && (0 < ai->size || aclinfo_may_indicate_xattr (ai)))
{
if (is_smack_enabled ())
{
- if (aclinfo_has_xattr (ai, XATTR_NAME_SMACK))
+ 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,
@@ -191,7 +223,7 @@ get_aclinfo (char const *name, struct aclinfo *ai, int flags)
else
{
# if USE_SELINUX_SELINUX_H
- if (aclinfo_has_xattr (ai, XATTR_NAME_SELINUX))
+ if (ai->size < 0 || aclinfo_has_xattr (ai, XATTR_NAME_SELINUX))
{
ssize_t r =
((flags & ACL_SYMLINK_FOLLOW ? getfilecon : lgetfilecon)
@@ -352,7 +384,7 @@ file_has_aclinfo (MAYBE_UNUSED char const *restrict name,
int initial_errno = errno;
get_aclinfo (name, ai, flags);
- if (ai->size <= 0)
+ if (!aclinfo_may_indicate_xattr (ai) && ai->size <= 0)
{
errno = ai->size < 0 ? ai->u.err : initial_errno;
return ai->size;
@@ -363,11 +395,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 (!aclinfo_has_xattr (ai, XATTR_NAME_NFSV4_ACL))
+ if (!has_xattr (XATTR_NAME_NFSV4_ACL, ai, name, flags))
return
- (aclinfo_has_xattr (ai, XATTR_NAME_POSIX_ACL_ACCESS)
+ (has_xattr (XATTR_NAME_POSIX_ACL_ACCESS, ai, name, flags)
|| ((d_type == DT_DIR || d_type == DT_UNKNOWN)
- && aclinfo_has_xattr (ai, XATTR_NAME_POSIX_ACL_DEFAULT)));
+ && has_xattr (XATTR_NAME_POSIX_ACL_DEFAULT, ai, 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,
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index a42e77e99b8..b1f0053e582 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -489,6 +489,8 @@ GL_GNULIB_MBSSPN = @GL_GNULIB_MBSSPN@
GL_GNULIB_MBSSTR = @GL_GNULIB_MBSSTR@
GL_GNULIB_MBSTOK_R = @GL_GNULIB_MBSTOK_R@
GL_GNULIB_MBSTOWCS = @GL_GNULIB_MBSTOWCS@
+GL_GNULIB_MBS_ENDSWITH = @GL_GNULIB_MBS_ENDSWITH@
+GL_GNULIB_MBS_STARTSWITH = @GL_GNULIB_MBS_STARTSWITH@
GL_GNULIB_MBTOWC = @GL_GNULIB_MBTOWC@
GL_GNULIB_MDA_ACCESS = @GL_GNULIB_MDA_ACCESS@
GL_GNULIB_MDA_CHDIR = @GL_GNULIB_MDA_CHDIR@
@@ -642,6 +644,8 @@ GL_GNULIB_STRTOUL = @GL_GNULIB_STRTOUL@
GL_GNULIB_STRTOULL = @GL_GNULIB_STRTOULL@
GL_GNULIB_STRTOUMAX = @GL_GNULIB_STRTOUMAX@
GL_GNULIB_STRVERSCMP = @GL_GNULIB_STRVERSCMP@
+GL_GNULIB_STR_ENDSWITH = @GL_GNULIB_STR_ENDSWITH@
+GL_GNULIB_STR_STARTSWITH = @GL_GNULIB_STR_STARTSWITH@
GL_GNULIB_SYMLINK = @GL_GNULIB_SYMLINK@
GL_GNULIB_SYMLINKAT = @GL_GNULIB_SYMLINKAT@
GL_GNULIB_SYSTEM_POSIX = @GL_GNULIB_SYSTEM_POSIX@
@@ -3655,6 +3659,8 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
-e 's/@''GNULIB_MBSSPN''@/$(GL_GNULIB_MBSSPN)/g' \
-e 's/@''GNULIB_MBSSEP''@/$(GL_GNULIB_MBSSEP)/g' \
-e 's/@''GNULIB_MBSTOK_R''@/$(GL_GNULIB_MBSTOK_R)/g' \
+ -e 's/@''GNULIB_MBS_ENDSWITH''@/$(GL_GNULIB_MBS_ENDSWITH)/g' \
+ -e 's/@''GNULIB_MBS_STARTSWITH''@/$(GL_GNULIB_MBS_STARTSWITH)/g' \
-e 's/@''GNULIB_MEMCHR''@/$(GL_GNULIB_MEMCHR)/g' \
-e 's/@''GNULIB_MEMMEM''@/$(GL_GNULIB_MEMMEM)/g' \
-e 's/@''GNULIB_MEMPCPY''@/$(GL_GNULIB_MEMPCPY)/g' \
@@ -3673,6 +3679,8 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
-e 's/@''GNULIB_STRSTR''@/$(GL_GNULIB_STRSTR)/g' \
-e 's/@''GNULIB_STRCASESTR''@/$(GL_GNULIB_STRCASESTR)/g' \
-e 's/@''GNULIB_STRTOK_R''@/$(GL_GNULIB_STRTOK_R)/g' \
+ -e 's/@''GNULIB_STR_ENDSWITH''@/$(GL_GNULIB_STR_ENDSWITH)/g' \
+ -e 's/@''GNULIB_STR_STARTSWITH''@/$(GL_GNULIB_STR_STARTSWITH)/g' \
-e 's/@''GNULIB_STRERROR''@/$(GL_GNULIB_STRERROR)/g' \
-e 's/@''GNULIB_STRERROR_R''@/$(GL_GNULIB_STRERROR_R)/g' \
-e 's/@''GNULIB_STRERRORNAME_NP''@/$(GL_GNULIB_STRERRORNAME_NP)/g' \
diff --git a/lib/mktime-internal.h b/lib/mktime-internal.h
index 1da98b43732..215be914c2f 100644
--- a/lib/mktime-internal.h
+++ b/lib/mktime-internal.h
@@ -19,6 +19,9 @@
#ifndef _LIBC
# include <time.h>
+# define __libc_lock_lock(lock) ((void) 0)
+# define __libc_lock_unlock(lock) ((void) 0)
+# define __tzset_unlocked() tzset ()
#endif
/* mktime_offset_t is a signed type wide enough to hold a UTC offset
@@ -73,6 +76,8 @@ typedef int mktime_offset_t;
/* Subroutine of mktime. Return the time_t representation of TP and
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. */
+ Record next guess for localtime-gmtime offset in *OFFSET.
+
+ If _LIBC, the caller must lock __tzset_lock. */
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 74403e4530e..4218fca69b1 100644
--- a/lib/mktime.c
+++ b/lib/mktime.c
@@ -62,6 +62,9 @@
# define NEED_MKTIME_WORKING 0
#endif
+#ifdef _LIBC
+# include <tzset.h>
+#endif
#include "mktime-internal.h"
#if !defined _LIBC && (NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS)
@@ -98,8 +101,8 @@ my_tzset (void)
tzset ();
# endif
}
-# undef __tzset
-# define __tzset() my_tzset ()
+# undef tzset
+# define tzset() my_tzset ()
#endif
#if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL
@@ -250,6 +253,7 @@ tm_diff (long_int year, long_int yday, int hour, int min, int sec,
tp->tm_hour, tp->tm_min, tp->tm_sec);
}
+#ifndef _LIBC
/* 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. */
@@ -262,8 +266,8 @@ convert_time (long_int t, bool local, struct tm *tm)
else
return __gmtime64_r (&x, tm);
}
-/* Call it __tzconvert to sync with other parts of glibc. */
-#define __tz_convert convert_time
+# define __tz_convert convert_time
+#endif
/* 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
@@ -320,7 +324,9 @@ ranged_convert (bool local, long_int *t, struct tm *tp)
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. */
+ This function is external because it is used also by timegm.c.
+
+ If _LIBC, the caller must lock __tzset_lock. */
__time64_t
__mktime_internal (struct tm *tp, bool local, mktime_offset_t *offset)
{
@@ -349,12 +355,10 @@ __mktime_internal (struct tm *tp, bool local, mktime_offset_t *offset)
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;
+ /* True if the previous probe was DST. */
+ bool dst2 = false;
/* Ensure that mon is in range, and set year accordingly. */
int mon_remainder = mon % 12;
@@ -443,13 +447,10 @@ __mktime_internal (struct tm *tp, bool local, mktime_offset_t *offset)
Heuristic: probe the adjacent timestamps in both directions,
looking for the desired isdst. If none is found within a
- reasonable duration bound, assume a one-hour DST difference.
+ reasonable duration bound, ignore the disagreement.
This should work for all real time zone histories in the tz
database. */
- /* +1 if we wanted standard time but got DST, -1 if the reverse. */
- int dst_difference = (isdst == 0) - (tm.tm_isdst == 0);
-
/* Distance between probes when looking for a DST boundary. In
tzdata2003a, the shortest period of DST is 601200 seconds
(e.g., America/Recife starting 2000-10-08 01:00), and the
@@ -459,21 +460,17 @@ __mktime_internal (struct tm *tp, bool local, mktime_offset_t *offset)
periods when probing. */
int stride = 601200;
- /* In TZDB 2021e, the longest period of DST (or of non-DST), in
- which the DST (or adjacent DST) difference is not one hour,
- is 457243209 seconds: e.g., America/Cambridge_Bay with leap
- seconds, starting 1965-10-31 00:00 in a switch from
- double-daylight time (-05) to standard time (-07), and
- continuing to 1980-04-27 02:00 in a switch from standard time
- (-07) to daylight time (-06). */
- int duration_max = 457243209;
-
- /* Search in both directions, so the maximum distance is half
- the duration; add the stride to avoid off-by-1 problems. */
- int delta_bound = duration_max / 2 + stride;
+ /* Do not probe too far away from the requested time,
+ by striding until at least a year has passed, but then giving up.
+ This helps avoid unexpected results in (for example) Asia/Kolkata,
+ for which today's users expect to see no DST even though it
+ did observe DST long ago. */
+ int year_seconds_bound = 366 * 24 * 60 * 60 + 1;
+ int delta_bound = year_seconds_bound + stride;
int delta, direction;
+ /* Search in both directions, closest first. */
for (delta = stride; delta < delta_bound; delta += stride)
for (direction = -1; direction <= 1; direction += 2)
{
@@ -503,13 +500,8 @@ __mktime_internal (struct tm *tp, bool local, mktime_offset_t *offset)
}
}
- /* No unusual DST offset was found nearby. Assume one-hour DST. */
- t += 60 * 60 * dst_difference;
- if (mktime_min <= t && t <= mktime_max && __tz_convert (t, local, &tm))
- goto offset_found;
-
- __set_errno (EOVERFLOW);
- return -1;
+ /* No probe with the requested tm_isdst was found nearby.
+ Ignore the requested tm_isdst. */
}
offset_found:
@@ -548,17 +540,19 @@ __mktime_internal (struct tm *tp, bool local, mktime_offset_t *offset)
__time64_t
__mktime64 (struct tm *tp)
{
- /* POSIX.1 requires mktime to set external variables like 'tzname'
- as though tzset had been called. */
- __tzset ();
+ __libc_lock_lock (__tzset_lock);
+ __tzset_unlocked ();
# if defined _LIBC || NEED_MKTIME_WORKING
static mktime_offset_t localtime_offset;
- return __mktime_internal (tp, true, &localtime_offset);
+ __time64_t result = __mktime_internal (tp, true, &localtime_offset);
# else
# undef mktime
- return mktime (tp);
+ __time64_t result = mktime (tp);
# endif
+
+ __libc_lock_unlock (__tzset_lock);
+ return result;
}
#endif /* _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS */
diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h
index f8e2a6ce344..bd82086ff37 100644
--- a/lib/stdlib.in.h
+++ b/lib/stdlib.in.h
@@ -62,8 +62,9 @@
/* NetBSD 5.0 mis-defines NULL. */
#include <stddef.h>
-/* MirBSD 10 defines WEXITSTATUS in <sys/wait.h>, not in <stdlib.h>. */
-#if @GNULIB_SYSTEM_POSIX@ && !defined WEXITSTATUS
+/* MirBSD 10 defines WEXITSTATUS in <sys/wait.h>, not in <stdlib.h>.
+ glibc 2.40 defines WCOREDUMP in <sys/wait.h>, not in <stdlib.h>. */
+#if @GNULIB_SYSTEM_POSIX@ && !(defined WEXITSTATUS && defined WCOREDUMP)
# include <sys/wait.h>
#endif
diff --git a/lib/string.in.h b/lib/string.in.h
index 1bae32ad465..ce488299006 100644
--- a/lib/string.in.h
+++ b/lib/string.in.h
@@ -1077,6 +1077,22 @@ _GL_WARN_ON_USE (strtok_r, "strtok_r is unportable - "
/* The following functions are not specified by POSIX. They are gnulib
extensions. */
+#if @GNULIB_STR_STARTSWITH@
+/* Returns true if STRING starts with PREFIX.
+ Returns false otherwise. */
+_GL_EXTERN_C bool str_startswith (const char *string, const char *prefix)
+ _GL_ATTRIBUTE_PURE
+ _GL_ARG_NONNULL ((1, 2));
+#endif
+
+#if @GNULIB_STR_ENDSWITH@
+/* Returns true if STRING ends with SUFFIX.
+ Returns false otherwise. */
+_GL_EXTERN_C bool str_endswith (const char *string, const char *prefix)
+ _GL_ATTRIBUTE_PURE
+ _GL_ARG_NONNULL ((1, 2));
+#endif
+
#if @GNULIB_MBSLEN@
/* Return the number of multibyte characters in the character string STRING.
This considers multibyte characters, unlike strlen, which counts bytes. */
@@ -1301,6 +1317,26 @@ _GL_EXTERN_C char * mbstok_r (char *restrict string, const char *delim,
_GL_ARG_NONNULL ((2, 3));
#endif
+#if @GNULIB_MBS_STARTSWITH@
+/* Returns true if STRING starts with PREFIX.
+ Returns false otherwise. */
+_GL_EXTERN_C bool mbs_startswith (const char *string, const char *prefix)
+ _GL_ATTRIBUTE_PURE
+ _GL_ARG_NONNULL ((1, 2));
+/* No extra code is needed for multibyte locales for this function. */
+# define mbs_startswith str_startswith
+#endif
+
+#if @GNULIB_MBS_ENDSWITH@
+/* Returns true if STRING ends with SUFFIX.
+ Returns false otherwise.
+ Unlike str_endswith(), this function works correctly in multibyte locales.
+ */
+_GL_EXTERN_C bool mbs_endswith (const char *string, const char *suffix)
+ _GL_ATTRIBUTE_PURE
+ _GL_ARG_NONNULL ((1, 2));
+#endif
+
/* Map any int, typically from errno, into an error message. */
#if @GNULIB_STRERROR@
# if @REPLACE_STRERROR@
diff --git a/lib/sys_select.in.h b/lib/sys_select.in.h
index fd3e28fd8e0..a06725020d2 100644
--- a/lib/sys_select.in.h
+++ b/lib/sys_select.in.h
@@ -165,12 +165,18 @@
#if @HAVE_WINSOCK2_H@
+/* Define type 'suseconds_t'. */
+# if !GNULIB_defined_suseconds_t
+typedef int suseconds_t;
+# define GNULIB_defined_suseconds_t 1
+# endif
+
# if !GNULIB_defined_rpl_fd_isset
/* Re-define FD_ISSET to avoid a WSA call while we are not using
network sockets. */
static int
-rpl_fd_isset (SOCKET fd, fd_set * set)
+rpl_fd_isset (SOCKET fd, const fd_set * set)
{
u_int i;
if (set == NULL)