Update from Gnulib by running admin/merge-gnulib

* admin/merge-gnulib (AVOIDED_MODULES): Add strncpy, as Emacs is not
likely to exercise the FreeBSD 15 strncpy bug that this module fixes.
* lib/issymlinkat.h: New file, taken from Gnulib.
This commit is contained in:
Paul Eggert 2025-12-07 15:34:42 -08:00
parent 0d43f2a562
commit b211e5489b
25 changed files with 383 additions and 195 deletions

View file

@ -61,7 +61,7 @@ AVOIDED_MODULES='
localcharset locale-h localename-unsafe-limited lock
mbrtowc mbsinit memchr mkdir msvc-inval msvc-nothrow nl_langinfo
openat-die opendir pthread-h raise
save-cwd select setenv sigprocmask stat std-gnu11 stdarg-h
save-cwd select setenv sigprocmask stat std-gnu11 stdarg-h strncpy
threadlib tzset unsetenv utime utime-h
wchar-h wcrtomb wctype wctype-h
'

View file

@ -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-10-25.20}
\def\texinfoversion{2025-12-06.19}
%
% Copyright 1985, 1986, 1988, 1990-2025 Free Software Foundation, Inc.
%
@ -335,7 +335,7 @@
%
% Make the heading and footing. \makeheadline and \makefootline
% use the contents of \headline and \footline.
\def\commonheadfootline{\let\hsize=\txipagewidth \texinfochars}
\def\commonheadfootline{\let\hsize=\txipagewidth \texinfochars}%
\ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi
\global\setbox\headlinebox = \vbox{\commonheadfootline \makeheadline}%
\ifodd\pageno \getoddfootingmarks \else \getevenfootingmarks \fi
@ -558,7 +558,13 @@
\def\:{\spacefactor=1000 }
% @* forces a line break.
\def\*{\unskip\hfil\break\hbox{}\ignorespaces}
% In internal horizontal or vertical mode, convert explicit line breaks
% from @* into spaces. For instance, if the user gives these in long
% section titles, this may occur in the table of contents, or the page
% heading line.
\def\*{%
\ifinner\unskip\space\ignorespaces
\else\unskip\hfil\break\hbox{}\ignorespaces\fi}
% @/ allows a line break.
\let\/=\allowbreak
@ -5681,14 +5687,16 @@
\def\indexentry#1#2{%
\let\entrypagetarget\empty
\ifpdforxetex
% only link the index text to the page if no comma appears in the
% list of pages, i.e. there is only one page
\checkpagelistcomma{#2}\pagelistcomma
\expandafter\ifcase\pagelistcomma
\def\entrypagetarget{#2}%
\fi
\fi%
\ifflagclear{txilinkindextext}{}{%
\ifpdforxetex
% link the index text to the page if no comma appears in the
% list of pages, i.e. there is only one page
\checkpagelistcomma{#2}\pagelistcomma
\expandafter\ifcase\pagelistcomma
\def\entrypagetarget{#2}%
\fi
\fi%
}%
\entryinternal{#1}{#2}%
}
@ -5783,9 +5791,10 @@
\def\indexrbrace{\}}%
\def\indexbackslash{\realbackslash}%
\def\indexatchar{\@}%
\writetocentry{idxinitial}{\asis #1}{IDX\the\idxinitialno}%
\writetocentry{idxinitial}{\asis #1\empty}{IDX\the\idxinitialno}%
% The @asis removes a pair of braces around e.g. {@indexatchar} that
% are output by texindex.
% are output by texindex. \empty is an argument to \asis in case #1
% is empty.
%
\pdfmkdest{idx.\asis #1.IDX\the\idxinitialno}%
\fi
@ -5827,10 +5836,6 @@
% No extra space above this paragraph.
\parskip = 0in
%
% When reading the text of entry, convert explicit line breaks
% from @* into spaces. The user might give these in long section
% titles, for instance.
\def\*{\unskip\space\ignorespaces}%
\def\entrybreak{\hfil\break}% An undocumented command
%
% Swallow the left brace of the text (first parameter):
@ -6191,10 +6196,17 @@
% and \thissection, as is done in \startcontents.
\let\pchapsepmacro\relax
\chapmacro{}{Yomitfromtoc}{}%
\gdef\thispart{#1}%
\chapoddpage
\endgroup
}
% Name of current part, if any.
% Note: unlike @thischapter etc. defined below, the name of the part
% is always set before a page with a heading or footing is shipped out,
% so there is no need to keep the value of these in "marks".
\def\thispart{}%
% \unnumberedno is an oxymoron. But we count the unnumbered
% sections so that we can refer to them unambiguously in the pdf
% outlines by their "section number". We avoid collisions with chapter

View file

@ -257,7 +257,7 @@
calls to the function with the same arguments, so long as the state
addressed by its arguments is the same.
This attribute is safe for a function that is effectless, idempotent,
stateless, and independent; see ISO C 23 § 6.7.12.7 for a definition of
stateless, and independent; see ISO C 23 § 6.7.13.8 for a definition of
these terms.
(This attribute is stricter than REPRODUCIBLE because the function
must be stateless and independent. It is looser than ATTRIBUTE_CONST
@ -266,7 +266,7 @@
See also <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2956.htm> and
<https://stackoverflow.com/questions/76847905/>.
ATTENTION! Efforts are underway to change the meaning of this attribute.
See <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3424.htm>. */
See <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3494.htm>. */
/* Applies to: functions, pointer to functions, function type. */
#define UNSEQUENCED _GL_ATTRIBUTE_UNSEQUENCED
@ -287,7 +287,7 @@
addressed by its arguments is the same and is updated in time for
the rest of the program.
This attribute is safe for a function that is effectless and idempotent; see
ISO C 23 § 6.7.12.7 for a definition of these terms.
ISO C 23 § 6.7.13.8 for a definition of these terms.
(This attribute is looser than UNSEQUENCED because the function need
not be stateless and idempotent. It is looser than ATTRIBUTE_PURE
because the function need not return exactly once and can affect
@ -295,7 +295,7 @@
See also <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2956.htm> and
<https://stackoverflow.com/questions/76847905/>.
ATTENTION! Efforts are underway to change the meaning of this attribute.
See <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3424.htm>. */
See <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3494.htm>. */
/* Applies to: functions, pointer to functions, function type. */
#define REPRODUCIBLE _GL_ATTRIBUTE_REPRODUCIBLE

View file

@ -114,10 +114,10 @@ klibc_dup2dirfd (int fd, int desired_fd)
int dupfd;
tempfd = open ("NUL", O_RDONLY);
if (tempfd == -1)
return -1;
if (tempfd < 0)
return tempfd;
if (tempfd == desired_fd)
if (tempfd >= desired_fd)
{
close (tempfd);
@ -125,7 +125,29 @@ klibc_dup2dirfd (int fd, int desired_fd)
if (__libc_Back_ioFHToPath (fd, path, sizeof (path)))
return -1;
return open(path, O_RDONLY);
for (;;)
{
close (desired_fd);
dupfd = open (path, O_RDONLY);
if (dupfd < 0)
return dupfd;
if (dupfd == desired_fd)
return dupfd;
/* If lower FD was closed by other threads, fill again. */
if (dupfd < desired_fd)
{
tempfd = dupfd;
break;
}
/* desired_fd was opened by other threads. Try again. */
/* FIXME: Closing desired_fd opened by other threads may lead to
unexpected behavior. */
close (dupfd);
}
}
dupfd = klibc_dup2dirfd (fd, desired_fd);
@ -142,13 +164,9 @@ klibc_dup2 (int fd, int desired_fd)
struct stat sbuf;
dupfd = dup2 (fd, desired_fd);
if (dupfd == -1 && errno == ENOTSUP \
if (dupfd < 0 && errno == ENOTSUP \
&& !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode))
{
close (desired_fd);
return klibc_dup2dirfd (fd, desired_fd);
}
return klibc_dup2dirfd (fd, desired_fd);
return dupfd;
}
@ -179,10 +197,11 @@ rpl_dup2 (int fd, int desired_fd)
result = dup2 (fd, desired_fd);
/* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x. */
if (result == -1 && errno == EMFILE)
if (result < 0 && errno == EMFILE)
errno = EBADF;
#if REPLACE_FCHDIR
if (fd != desired_fd && result != -1)
if (! (result < 0 || fd == desired_fd))
result = _gl_register_dup (fd, result);
#endif
return result;

View file

@ -46,7 +46,7 @@ orig_fchmodat (int dir, char const *file, mode_t mode, int flags)
#include <intprops.h>
#include "issymlink.h"
#include "issymlinkat.h"
/* Invoke chmod or lchmod on FILE, using mode MODE, in the directory
open on descriptor FD. If possible, do it without changing the

View file

@ -29,8 +29,8 @@
#include <unistd.h>
#ifdef __KLIBC__
# define INCL_DOS
# include <os2.h>
# include <emx/io.h>
# include <InnoTekLIBC/backend.h>
#endif
#if defined _WIN32 && ! defined __CYGWIN__
@ -539,6 +539,41 @@ rpl_fcntl_DUPFD_CLOEXEC (int fd, int target)
#undef fcntl
#ifdef __KLIBC__
static int
klibc_dupdirfd (int fd, int minfd)
{
int tempfd;
int dupfd;
tempfd = open ("NUL", O_RDONLY);
if (tempfd == -1)
return -1;
if (tempfd >= minfd)
{
close (tempfd);
char path[_MAX_PATH];
if (__libc_Back_ioFHToPath (fd, path, sizeof (path)))
return -1;
dupfd = open (path, O_RDONLY);
if (dupfd == -1)
return -1;
if (dupfd >= minfd)
return dupfd;
/* Lower FD was closed by other threads. Fill again. */
tempfd = dupfd;
}
dupfd = klibc_dupdirfd (fd, minfd);
close (tempfd);
return dupfd;
}
static int
klibc_fcntl (int fd, int action, /* arg */...)
@ -555,46 +590,50 @@ klibc_fcntl (int fd, int action, /* arg */...)
if (result == -1 && (errno == EPERM || errno == ENOTSUP)
&& !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode))
{
ULONG ulMode;
PLIBCFH pFH;
unsigned fFlags;
switch (action)
{
case F_DUPFD:
/* Find available fd */
while (fcntl (arg, F_GETFL) != -1 || errno != EBADF)
arg++;
result = dup2 (fd, arg);
result = klibc_dupdirfd (fd, arg);
break;
/* Using underlying APIs is right ? */
case F_GETFD:
if (DosQueryFHState (fd, &ulMode))
break;
pFH = __libc_FH (fd);
if (!pFH)
{
errno = EBADF;
break;
}
result = (ulMode & OPEN_FLAGS_NOINHERIT) ? FD_CLOEXEC : 0;
result = (pFH->fFlags & ((FD_CLOEXEC << __LIBC_FH_FDFLAGS_SHIFT )
| O_NOINHERIT)) ? FD_CLOEXEC : 0;
break;
case F_SETFD:
if (arg & ~FD_CLOEXEC)
break;
if (DosQueryFHState (fd, &ulMode))
break;
pFH = __libc_FH (fd);
if (!pFH)
{
errno = EBADF;
break;
}
fFlags = pFH->fFlags;
if (arg & FD_CLOEXEC)
ulMode |= OPEN_FLAGS_NOINHERIT;
fFlags |= (FD_CLOEXEC << __LIBC_FH_FDFLAGS_SHIFT) | O_NOINHERIT;
else
ulMode &= ~OPEN_FLAGS_NOINHERIT;
fFlags &= ~((FD_CLOEXEC << __LIBC_FH_FDFLAGS_SHIFT) | O_NOINHERIT);
/* Filter supported flags. */
ulMode &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR
| OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT);
if (DosSetFHState (fd, ulMode))
break;
result = 0;
result = __libc_FHSetFlags (pFH, fd, fFlags);
if (result < 0)
{
errno = -result;
result = -1;
}
break;
case F_GETFL:

View file

@ -399,9 +399,9 @@ acl_get_link_np (char const *name, acl_type_t type)
if (fd < 0)
return NULL;
acl_t r = acl_get_fd (fd);
int err = errno;
int saved_errno = errno;
close (fd);
errno = err;
errno = saved_errno;
return r;
}
# define HAVE_ACL_GET_LINK_NP 1

View file

@ -44,9 +44,9 @@ rpl_free (void *p)
free (p);
errno = err[errno == 0];
# else
int err = errno;
int saved_errno = errno;
free (p);
errno = err;
errno = saved_errno;
# endif
}

View file

@ -551,11 +551,11 @@ getloadavg (double loadavg[], int nelem)
if (fd < 0)
return fd;
int nread = read (fd, readbuf, sizeof readbuf - 1);
int err = errno;
int saved_errno = errno;
close (fd);
if (nread < 0)
{
errno = err;
errno = saved_errno;
return -1;
}
readbuf[nread] = '\0';

View file

@ -71,6 +71,7 @@
# --avoid=stat \
# --avoid=std-gnu11 \
# --avoid=stdarg-h \
# --avoid=strncpy \
# --avoid=threadlib \
# --avoid=tzset \
# --avoid=unsetenv \
@ -631,6 +632,7 @@ GL_GNULIB_STRERROR_R = @GL_GNULIB_STRERROR_R@
GL_GNULIB_STRFTIME = @GL_GNULIB_STRFTIME@
GL_GNULIB_STRINGEQ = @GL_GNULIB_STRINGEQ@
GL_GNULIB_STRNCAT = @GL_GNULIB_STRNCAT@
GL_GNULIB_STRNCPY = @GL_GNULIB_STRNCPY@
GL_GNULIB_STRNDUP = @GL_GNULIB_STRNDUP@
GL_GNULIB_STRNLEN = @GL_GNULIB_STRNLEN@
GL_GNULIB_STRPBRK = @GL_GNULIB_STRPBRK@
@ -1327,6 +1329,7 @@ REPLACE_STRERROR_L = @REPLACE_STRERROR_L@
REPLACE_STRERROR_R = @REPLACE_STRERROR_R@
REPLACE_STRFTIME = @REPLACE_STRFTIME@
REPLACE_STRNCAT = @REPLACE_STRNCAT@
REPLACE_STRNCPY = @REPLACE_STRNCPY@
REPLACE_STRNDUP = @REPLACE_STRNDUP@
REPLACE_STRNLEN = @REPLACE_STRNLEN@
REPLACE_STRSIGNAL = @REPLACE_STRSIGNAL@
@ -2650,7 +2653,7 @@ ifneq (,$(gl_GNULIB_ENABLED_issymlinkat_CONDITION))
libgnu_a_SOURCES += issymlinkat.c
endif
EXTRA_DIST += issymlink.h
EXTRA_DIST += issymlinkat.h
endif
## end gnulib module issymlinkat
@ -3757,6 +3760,7 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
-e 's/@''GNULIB_STRDUP''@/$(GL_GNULIB_STRDUP)/g' \
-e 's/@''GNULIB_STRINGEQ''@/$(GL_GNULIB_STRINGEQ)/g' \
-e 's/@''GNULIB_STRNCAT''@/$(GL_GNULIB_STRNCAT)/g' \
-e 's/@''GNULIB_STRNCPY''@/$(GL_GNULIB_STRNCPY)/g' \
-e 's/@''GNULIB_STRNDUP''@/$(GL_GNULIB_STRNDUP)/g' \
-e 's/@''GNULIB_STRNLEN''@/$(GL_GNULIB_STRNLEN)/g' \
-e 's/@''GNULIB_STRPBRK''@/$(GL_GNULIB_STRPBRK)/g' \
@ -3818,6 +3822,7 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
-e 's|@''REPLACE_STRCHRNUL''@|$(REPLACE_STRCHRNUL)|g' \
-e 's|@''REPLACE_STRDUP''@|$(REPLACE_STRDUP)|g' \
-e 's|@''REPLACE_STRNCAT''@|$(REPLACE_STRNCAT)|g' \
-e 's|@''REPLACE_STRNCPY''@|$(REPLACE_STRNCPY)|g' \
-e 's|@''REPLACE_STRNDUP''@|$(REPLACE_STRNDUP)|g' \
-e 's|@''REPLACE_STRNLEN''@|$(REPLACE_STRNLEN)|g' \
-e 's|@''REPLACE_STRSTR''@|$(REPLACE_STRSTR)|g' \

View file

@ -23,7 +23,7 @@
#endif
#include <errno.h>
#include <unistd.h> /* for readlink, readlinkat */
#include <unistd.h> /* for readlink */
_GL_INLINE_HEADER_BEGIN
@ -31,11 +31,7 @@ _GL_INLINE_HEADER_BEGIN
#ifndef _GL_ISSYMLINK_INLINE
# define _GL_ISSYMLINK_INLINE _GL_INLINE
#endif
#ifndef _GL_ISSYMLINKAT_INLINE
# define _GL_ISSYMLINKAT_INLINE _GL_INLINE
#endif
#if GNULIB_ISSYMLINK
/* Tests whether FILENAME represents a symbolic link.
This function is more reliable than lstat() / fstatat() followed by S_ISLNK,
because it avoids possible EOVERFLOW errors.
@ -44,9 +40,9 @@ _GL_INLINE_HEADER_BEGIN
0 if FILENAME exists and is not a symbolic link,
-1 with errno set if determination failed, in particular
-1 with errno = ENOENT or ENOTDIR if FILENAME does not exist. */
# ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
# endif
#endif
_GL_ISSYMLINK_INLINE int issymlink (const char *filename)
_GL_ARG_NONNULL ((1));
_GL_ISSYMLINK_INLINE int
@ -60,42 +56,8 @@ issymlink (const char *filename)
else
return -1;
}
# ifdef __cplusplus
#ifdef __cplusplus
}
# endif
#endif
#if GNULIB_ISSYMLINKAT
/* Tests whether FILENAME represents a symbolic link.
This function is more reliable than lstat() / fstatat() followed by S_ISLNK,
because it avoids possible EOVERFLOW errors.
If FILENAME is a relative file name, it is interpreted as relative to the
directory referred to by FD (where FD = AT_FDCWD denotes the current
directory).
Returns
1 if FILENAME is a symbolic link,
0 if FILENAME exists and is not a symbolic link,
-1 with errno set if determination failed, in particular
-1 with errno = ENOENT or ENOTDIR if FILENAME does not exist. */
# ifdef __cplusplus
extern "C" {
# endif
_GL_ISSYMLINKAT_INLINE int issymlinkat (int fd, const char *filename)
_GL_ARG_NONNULL ((2));
_GL_ISSYMLINKAT_INLINE int
issymlinkat (int fd, const char *filename)
{
char linkbuf[1];
if (readlinkat (fd, filename, linkbuf, sizeof (linkbuf)) >= 0)
return 1;
if (errno == EINVAL)
return 0;
else
return -1;
}
# ifdef __cplusplus
}
# endif
#endif
_GL_INLINE_HEADER_END

View file

@ -17,4 +17,4 @@
#include <config.h>
#define _GL_ISSYMLINKAT_INLINE _GL_EXTERN_INLINE
#include "issymlink.h"
#include "issymlinkat.h"

68
lib/issymlinkat.h Normal file
View file

@ -0,0 +1,68 @@
/* Test whether a file is a symbolic link.
Copyright (C) 2025 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/>. */
#ifndef _ISSYMLINKAT_H
#define _ISSYMLINKAT_H
/* This file uses _GL_ARG_NONNULL, _GL_INLINE. */
#if !_GL_CONFIG_H_INCLUDED
#error "Please include config.h first."
#endif
#include <errno.h>
#include <unistd.h> /* for readlinkat */
_GL_INLINE_HEADER_BEGIN
#ifndef _GL_ISSYMLINKAT_INLINE
# define _GL_ISSYMLINKAT_INLINE _GL_INLINE
#endif
/* Tests whether FILENAME represents a symbolic link.
This function is more reliable than lstat() / fstatat() followed by S_ISLNK,
because it avoids possible EOVERFLOW errors.
If FILENAME is a relative file name, it is interpreted as relative to the
directory referred to by FD (where FD = AT_FDCWD denotes the current
directory).
Returns
1 if FILENAME is a symbolic link,
0 if FILENAME exists and is not a symbolic link,
-1 with errno set if determination failed, in particular
-1 with errno = ENOENT or ENOTDIR if FILENAME does not exist. */
#ifdef __cplusplus
extern "C" {
#endif
_GL_ISSYMLINKAT_INLINE int issymlinkat (int fd, const char *filename)
_GL_ARG_NONNULL ((2));
_GL_ISSYMLINKAT_INLINE int
issymlinkat (int fd, const char *filename)
{
char linkbuf[1];
if (readlinkat (fd, filename, linkbuf, sizeof (linkbuf)) >= 0)
return 1;
if (errno == EINVAL)
return 0;
else
return -1;
}
#ifdef __cplusplus
}
#endif
_GL_INLINE_HEADER_END
#endif /* _ISSYMLINKAT_H */

View file

@ -30,6 +30,7 @@
#include <intprops.h>
#include "issymlink.h"
#include "issymlinkat.h"
/* Work like chmod, except when FILE is a symbolic link.
In that case, on systems where permissions on symbolic links are unsupported

View file

@ -94,7 +94,7 @@ rpl_realloc (void *p, size_t n)
void *result = realloc (p, n1);
# if !HAVE_MALLOC_POSIX
# if !HAVE_REALLOC_POSIX
if (result == NULL)
errno = ENOMEM;
# endif

View file

@ -374,32 +374,34 @@ two_way_long_needle (const unsigned char *haystack, size_t haystack_len,
}
memory = 0;
j += shift;
continue;
}
/* Scan for matches in right half. The last byte has
already been matched, by virtue of the shift table. */
size_t i = MAX (suffix, memory);
while (i < needle_len - 1 && (CANON_ELEMENT (needle[i])
== CANON_ELEMENT (haystack[i + j])))
++i;
if (needle_len - 1 <= i)
{
/* Scan for matches in left half. */
i = suffix - 1;
while (memory < i + 1 && (CANON_ELEMENT (needle[i])
== CANON_ELEMENT (haystack[i + j])))
--i;
if (i + 1 < memory + 1)
return (RETURN_TYPE) (haystack + j);
/* No match, so remember how many repetitions of period
on the right half were scanned. */
j += period;
memory = needle_len - period;
}
else
{
j += i - suffix + 1;
memory = 0;
/* Scan for matches in right half. The last byte has
already been matched, by virtue of the shift table. */
size_t i = MAX (suffix, memory);
while (i < needle_len - 1 && (CANON_ELEMENT (needle[i])
== CANON_ELEMENT (haystack[i + j])))
++i;
if (needle_len - 1 <= i)
{
/* Scan for matches in left half. */
i = suffix - 1;
while (memory < i + 1 && (CANON_ELEMENT (needle[i])
== CANON_ELEMENT (haystack[i + j])))
--i;
if (i + 1 < memory + 1)
return (RETURN_TYPE) (haystack + j);
/* No match, so remember how many repetitions of period
on the right half were scanned. */
j += period;
memory = needle_len - period;
}
else
{
j += i - suffix + 1;
memory = 0;
}
}
}
}
@ -418,27 +420,29 @@ two_way_long_needle (const unsigned char *haystack, size_t haystack_len,
if (0 < shift)
{
j += shift;
continue;
}
/* Scan for matches in right half. The last byte has
already been matched, by virtue of the shift table. */
size_t i = suffix;
while (i < needle_len - 1 && (CANON_ELEMENT (needle[i])
== CANON_ELEMENT (haystack[i + j])))
++i;
if (needle_len - 1 <= i)
{
/* Scan for matches in left half. */
i = suffix - 1;
while (i != SIZE_MAX && (CANON_ELEMENT (needle[i])
== CANON_ELEMENT (haystack[i + j])))
--i;
if (i == SIZE_MAX)
return (RETURN_TYPE) (haystack + j);
j += period;
}
else
j += i - suffix + 1;
{
/* Scan for matches in right half. The last byte has
already been matched, by virtue of the shift table. */
size_t i = suffix;
while (i < needle_len - 1 && (CANON_ELEMENT (needle[i])
== CANON_ELEMENT (haystack[i + j])))
++i;
if (needle_len - 1 <= i)
{
/* Scan for matches in left half. */
i = suffix - 1;
while (i != SIZE_MAX && (CANON_ELEMENT (needle[i])
== CANON_ELEMENT (haystack[i + j])))
--i;
if (i == SIZE_MAX)
return (RETURN_TYPE) (haystack + j);
j += period;
}
else
j += i - suffix + 1;
}
}
}
return NULL;

View file

@ -840,6 +840,35 @@ _GL_WARN_ON_USE (strncat, "strncat is unportable - "
# endif
#endif
/* Copy no more than N bytes of SRC to DST, returning DST. */
#if @GNULIB_STRNCPY@
# if @REPLACE_STRNCPY@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef strncpy
# define strncpy rpl_strncpy
# endif
_GL_FUNCDECL_RPL (strncpy, char *,
(char *restrict __dst, char const *restrict __src,
size_t __n),
_GL_ARG_NONNULL ((1, 2)));
_GL_CXXALIAS_RPL (strncpy, char *,
(char *restrict __dst, char const *restrict __src,
size_t __n));
# else
_GL_CXXALIAS_SYS (strncpy, char *,
(char *restrict __dst, char const *restrict __src,
size_t __n));
# endif
# if __GLIBC__ >= 2
_GL_CXXALIASWARN (strncpy);
# endif
#elif defined GNULIB_POSIXCHECK
# if HAVE_RAW_DECL_STRNCPY
_GL_WARN_ON_USE (strncpy, "strncpy is unportable - "
"use gnulib module strncpy for portability");
# endif
#endif
/* Return a newly allocated copy of at most N bytes of STRING. */
#if @GNULIB_STRNDUP@
# if @REPLACE_STRNDUP@

View file

@ -57,9 +57,9 @@ void
tzfree (timezone_t tz)
# undef tzfree
{
int err = errno;
int saved_errno = errno;
tzfree (tz);
errno = err;
errno = saved_errno;
}
#else

View file

@ -44,7 +44,7 @@ AC_DEFUN([gl_EXTERN_INLINE],
if isdigit is mistakenly implemented via a static inline function,
a program containing an extern inline function that calls isdigit
may not work since C99 through C23 prohibit extern inline functions
from calling static functions (ISO C 23 section 6.7.5.(2)).
from calling static functions (ISO C 23 § 6.7.5 ¶ 3)).
Although a future C standard will likely relax this restriction
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3622.txt>,
respect it for now. This bug is known to occur on:

View file

@ -768,7 +768,7 @@ AC_DEFUN([gl_COMMON_BODY], [
addressed by its arguments is the same and is updated in time for
the rest of the program.
This attribute is safe for a function that is effectless and idempotent; see
ISO C 23 § 6.7.12.7 for a definition of these terms.
ISO C 23 § 6.7.13.8 for a definition of these terms.
(This attribute is looser than _GL_ATTRIBUTE_UNSEQUENCED because
the function need not be stateless and idempotent. It is looser
than _GL_ATTRIBUTE_PURE because the function need not return
@ -776,7 +776,7 @@ AC_DEFUN([gl_COMMON_BODY], [
See also <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2956.htm> and
<https://stackoverflow.com/questions/76847905/>.
ATTENTION! Efforts are underway to change the meaning of this attribute.
See <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3424.htm>. */
See <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3494.htm>. */
/* Applies to: functions, pointer to functions, function types. */
#ifndef _GL_ATTRIBUTE_REPRODUCIBLE
/* This may be revisited when gcc and clang support [[reproducible]] or possibly
@ -820,7 +820,7 @@ AC_DEFUN([gl_COMMON_BODY], [
calls to the function with the same arguments, so long as the state
addressed by its arguments is the same.
This attribute is safe for a function that is effectless, idempotent,
stateless, and independent; see ISO C 23 § 6.7.12.7 for a definition of
stateless, and independent; see ISO C 23 § 6.7.13.8 for a definition of
these terms.
(This attribute is stricter than _GL_ATTRIBUTE_REPRODUCIBLE because
the function must be stateless and independent. It is looser than
@ -829,7 +829,7 @@ AC_DEFUN([gl_COMMON_BODY], [
See also <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2956.htm> and
<https://stackoverflow.com/questions/76847905/>.
ATTENTION! Efforts are underway to change the meaning of this attribute.
See <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3424.htm>. */
See <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3494.htm>. */
/* Applies to: functions, pointer to functions, function types. */
#ifndef _GL_ATTRIBUTE_UNSEQUENCED
/* This may be revisited when gcc and clang support [[unsequenced]] or possibly

View file

@ -1383,6 +1383,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/issymlink.c
lib/issymlink.h
lib/issymlinkat.c
lib/issymlinkat.h
lib/lchmod.c
lib/libc-config.h
lib/limits.in.h

View file

@ -1,5 +1,5 @@
# malloc.m4
# serial 44
# serial 46
dnl Copyright (C) 2007, 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,
@ -99,7 +99,7 @@ AC_DEFUN([gl_FUNC_MALLOC_PTRDIFF],
[REPLACE_MALLOC_FOR_MALLOC_POSIX=1])
])
# Test whether malloc, realloc, calloc refuse to create objects
# Test whether malloc, calloc refuse to create objects
# larger than what can be expressed in ptrdiff_t.
# Set gl_cv_func_malloc_gnu.
AC_DEFUN([gl_CHECK_MALLOC_PTRDIFF],
@ -148,7 +148,7 @@ AC_DEFUN([gl_FUNC_MALLOC_POSIX],
case "$gl_cv_func_malloc_posix" in
*yes)
AC_DEFINE([HAVE_MALLOC_POSIX], [1],
[Define if malloc, realloc, and calloc set errno on allocation failure.])
[Define if malloc and calloc set errno on allocation failure.])
;;
*)
REPLACE_MALLOC_FOR_MALLOC_POSIX=1
@ -156,19 +156,20 @@ AC_DEFUN([gl_FUNC_MALLOC_POSIX],
esac
])
# Test whether malloc, realloc, calloc set errno to ENOMEM on failure.
# Test whether malloc, calloc set errno to ENOMEM on failure.
# Set gl_cv_func_malloc_posix to *yes or *no accordingly.
AC_DEFUN([gl_CHECK_MALLOC_POSIX],
[
AC_REQUIRE([AC_CANONICAL_HOST])
AC_CACHE_CHECK([whether malloc, realloc, calloc set errno on failure],
AC_CACHE_CHECK([whether malloc, calloc set errno on failure],
[gl_cv_func_malloc_posix],
[
dnl It is too dangerous to try to allocate a large amount of memory:
dnl some systems go to their knees when you do that. So assume that
dnl all Unix implementations of the function set errno on failure,
dnl except on those platforms where we have seen 'test-malloc-gnu',
dnl 'test-realloc-posix', 'test-calloc-gnu' fail.
dnl 'test-realloc-posix', 'test-calloc-gnu' fail. For platforms
dnl where only 'test-realloc-posix', see realloc.m4.
case "$host_os" in
mingw* | windows*)
dnl Old MSVCRT from 2001 did not set errno=ENOMEM when malloc failed.
@ -187,37 +188,41 @@ AC_DEFUN([gl_CHECK_MALLOC_POSIX],
[gl_cv_func_malloc_posix="guessing no"])
;;
solaris*)
dnl On Solaris 11.3, the three functions return NULL with errno set
dnl On Solaris 11.3, the three functions might fail with errno set
dnl to EAGAIN, not ENOMEM, when the argument is larger than
dnl PTRDIFF_MAX.
dnl PTRDIFF_MAX. See:
dnl https://lists.gnu.org/r/bug-gnulib/2021-05/msg00052.html
dnl Here is a test program:
m4_divert_push([KILL])
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#define ptrdiff_t long
#ifndef PTRDIFF_MAX
# define PTRDIFF_MAX ((ptrdiff_t) ((1UL << (8 * sizeof (ptrdiff_t) - 1)) - 1))
#endif
int main ()
#define TEST_CALL(call) \
do { \
void *p = call; \
if (p) \
fprintf (stderr, "returned %p (incorrect success)\n", p); \
else if (errno == ENOMEM) \
perror ("correct failure"); \
else \
perror ("incorrect failure (wrong errno)"); \
free (p); \
} while (0)
int
main ()
{
void *p;
fprintf (stderr, "PTRDIFF_MAX = %lu\n", (unsigned long) PTRDIFF_MAX);
errno = 0;
p = malloc ((unsigned long) PTRDIFF_MAX + 1);
fprintf (stderr, "p=%p errno=%d\n", p, errno);
errno = 0;
p = calloc (PTRDIFF_MAX / 2 + 1, 2);
fprintf (stderr, "p=%p errno=%d\n", p, errno);
errno = 0;
p = realloc (NULL, (unsigned long) PTRDIFF_MAX + 1);
fprintf (stderr, "p=%p errno=%d\n", p, errno);
size_t big = PTRDIFF_MAX;
TEST_CALL (malloc (big + 1));
TEST_CALL (calloc (big / 2 + 1, 2));
TEST_CALL (realloc (NULL, big + 1));
void *small = malloc (1);
TEST_CALL (realloc (small, big + 1));
free (small);
return 0;
}
m4_divert_pop([KILL])

View file

@ -1,5 +1,5 @@
# realloc.m4
# serial 39
# serial 40
dnl Copyright (C) 2007, 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,
@ -27,13 +27,54 @@ AC_DEFUN([gl_FUNC_REALLOC_POSIX],
[
AC_REQUIRE([gl_STDLIB_H_DEFAULTS])
AC_REQUIRE([gl_FUNC_MALLOC_POSIX])
AC_REQUIRE([AC_CANONICAL_HOST])
AC_CACHE_CHECK([whether realloc sets errno on failure],
[gl_cv_func_realloc_posix],
[
dnl FreeBSD 15.0 realloc() does not set errno when asked for more than
dnl 0x7000000000000000 bytes.
case "$host_os" in
darwin* | freebsd* | dragonfly* | midnightbsd* | netbsd* | openbsd*)
AC_RUN_IFELSE(
[AC_LANG_SOURCE(
[[#include <errno.h>
#include <stdlib.h>
int main (int argc, char **argv)
{
void *p;
errno = 1729;
p = realloc (malloc (1), (size_t)(-1) / 100 * 49);
return (!p && errno == 1729);
}
]])
],
[gl_cv_func_realloc_posix=yes],
[gl_cv_func_realloc_posix=no],
[case "$host_os" in
freebsd*) gl_cv_func_realloc_posix="guessing no" ;;
*) gl_cv_func_realloc_posix="guessing yes" ;;
esac
])
;;
*)
gl_cv_func_realloc_posix="$gl_cv_func_malloc_posix"
;;
esac
])
case "$gl_cv_func_realloc_posix" in
*yes)
AC_DEFINE([HAVE_REALLOC_POSIX], [1],
[Define if realloc sets errno on allocation failure.])
;;
*)
REPLACE_REALLOC_FOR_REALLOC_POSIX=1
;;
esac
AC_REQUIRE([gl_FUNC_REALLOC_SANITIZED])
if test "$gl_cv_func_realloc_sanitize" != no; then
REPLACE_REALLOC_FOR_REALLOC_POSIX=1
AC_DEFINE([NEED_SANITIZED_REALLOC], [1],
[Define to 1 if realloc should abort upon undefined behaviour.])
else
REPLACE_REALLOC_FOR_REALLOC_POSIX=$REPLACE_MALLOC_FOR_MALLOC_POSIX
fi
])

View file

@ -82,8 +82,8 @@ AC_DEFUN([gl_ALIGNASOF],
References:
ISO C23 (latest free draft
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3096.pdf>)
sections 6.5.3.4, 6.7.5, 7.15.
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf>)
sections 6.2.8, 6.7.6.
C++11 (latest free draft
<https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf>)
section 18.10. */

View file

@ -1,5 +1,5 @@
# string_h.m4
# serial 45
# serial 46
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,
@ -24,7 +24,7 @@ AC_DEFUN_ONCE([gl_STRING_H],
]],
[explicit_bzero ffsl ffsll memmem mempcpy memrchr memset_explicit
rawmemchr stpcpy stpncpy strchrnul
strdup strncat strndup strnlen strpbrk strsep strcasestr strtok_r
strdup strncat strncpy strndup strnlen strpbrk strsep strcasestr strtok_r
strerror_l strerror_r strerrorname_np
sigabbrev_np sigdescr_np strsignal strverscmp])
@ -65,6 +65,7 @@ AC_DEFUN([gl_STRING_H_REQUIRE_DEFAULTS],
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRDUP])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRINGEQ])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRNCAT])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRNCPY])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRNDUP])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRNLEN])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRPBRK])
@ -149,6 +150,7 @@ AC_DEFUN([gl_STRING_H_DEFAULTS],
REPLACE_STRCHRNUL=0; AC_SUBST([REPLACE_STRCHRNUL])
REPLACE_STRDUP=0; AC_SUBST([REPLACE_STRDUP])
REPLACE_STRNCAT=0; AC_SUBST([REPLACE_STRNCAT])
REPLACE_STRNCPY=0; AC_SUBST([REPLACE_STRNCPY])
REPLACE_STRNDUP=0; AC_SUBST([REPLACE_STRNDUP])
REPLACE_STRNLEN=0; AC_SUBST([REPLACE_STRNLEN])
REPLACE_STRSTR=0; AC_SUBST([REPLACE_STRSTR])