summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/attribute.h8
-rw-r--r--lib/dup2.c43
-rw-r--r--lib/fchmodat.c2
-rw-r--r--lib/fcntl.c87
-rw-r--r--lib/file-has-acl.c4
-rw-r--r--lib/free.c4
-rw-r--r--lib/getloadavg.c4
-rw-r--r--lib/gnulib.mk.in7
-rw-r--r--lib/issymlink.h46
-rw-r--r--lib/issymlinkat.c2
-rw-r--r--lib/issymlinkat.h68
-rw-r--r--lib/lchmod.c1
-rw-r--r--lib/realloc.c2
-rw-r--r--lib/str-two-way.h86
-rw-r--r--lib/string.in.h29
-rw-r--r--lib/time_rz.c4
16 files changed, 262 insertions, 135 deletions
diff --git a/lib/attribute.h b/lib/attribute.h
index c85412d90af..f24f5b18f1e 100644
--- a/lib/attribute.h
+++ b/lib/attribute.h
@@ -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
diff --git a/lib/dup2.c b/lib/dup2.c
index 69b37196dee..434e78c2bc6 100644
--- a/lib/dup2.c
+++ b/lib/dup2.c
@@ -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;
diff --git a/lib/fchmodat.c b/lib/fchmodat.c
index 9151778b8e3..4aa764f8510 100644
--- a/lib/fchmodat.c
+++ b/lib/fchmodat.c
@@ -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
diff --git a/lib/fcntl.c b/lib/fcntl.c
index 29cb4f9eb84..abdd7b89890 100644
--- a/lib/fcntl.c
+++ b/lib/fcntl.c
@@ -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:
diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c
index b1eb1f2e8e7..9a5a18aabcf 100644
--- a/lib/file-has-acl.c
+++ b/lib/file-has-acl.c
@@ -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
diff --git a/lib/free.c b/lib/free.c
index 394d8d13905..3a6577f13fa 100644
--- a/lib/free.c
+++ b/lib/free.c
@@ -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
}
diff --git a/lib/getloadavg.c b/lib/getloadavg.c
index f9ed97b04bd..ec7305f5d48 100644
--- a/lib/getloadavg.c
+++ b/lib/getloadavg.c
@@ -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';
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index 96d9cd8bd44..297af181c57 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -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' \
diff --git a/lib/issymlink.h b/lib/issymlink.h
index af6dc965645..a3f97cb5211 100644
--- a/lib/issymlink.h
+++ b/lib/issymlink.h
@@ -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
-}
-# 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
+#ifdef __cplusplus
}
-# endif
#endif
_GL_INLINE_HEADER_END
diff --git a/lib/issymlinkat.c b/lib/issymlinkat.c
index 8286356c8a2..ebd937e91bc 100644
--- a/lib/issymlinkat.c
+++ b/lib/issymlinkat.c
@@ -17,4 +17,4 @@
#include <config.h>
#define _GL_ISSYMLINKAT_INLINE _GL_EXTERN_INLINE
-#include "issymlink.h"
+#include "issymlinkat.h"
diff --git a/lib/issymlinkat.h b/lib/issymlinkat.h
new file mode 100644
index 00000000000..abbbbfff837
--- /dev/null
+++ b/lib/issymlinkat.h
@@ -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 */
diff --git a/lib/lchmod.c b/lib/lchmod.c
index deba4c50f5b..acccef629cc 100644
--- a/lib/lchmod.c
+++ b/lib/lchmod.c
@@ -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
diff --git a/lib/realloc.c b/lib/realloc.c
index 62efd5a39ff..cf0bf6e9f70 100644
--- a/lib/realloc.c
+++ b/lib/realloc.c
@@ -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
diff --git a/lib/str-two-way.h b/lib/str-two-way.h
index 852e5d078f2..1da773eb70e 100644
--- a/lib/str-two-way.h
+++ b/lib/str-two-way.h
@@ -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)
+ else
{
- /* 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;
+ /* 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;
}
- else
- j += i - suffix + 1;
}
}
return NULL;
diff --git a/lib/string.in.h b/lib/string.in.h
index a323b1cd6da..f316878b4c9 100644
--- a/lib/string.in.h
+++ b/lib/string.in.h
@@ -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@
diff --git a/lib/time_rz.c b/lib/time_rz.c
index 8a8eb44c357..116ac39ad2d 100644
--- a/lib/time_rz.c
+++ b/lib/time_rz.c
@@ -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