diff options
| author | Paul Eggert <eggert@cs.ucla.edu> | 2025-12-07 15:34:42 -0800 |
|---|---|---|
| committer | Paul Eggert <eggert@cs.ucla.edu> | 2025-12-07 15:45:20 -0800 |
| commit | b211e5489b95f39f07baa769fc581b05b393c4a3 (patch) | |
| tree | 34f59c09f3779fdf25f32bccbe8aa48491ee5b4f /lib | |
| parent | 0d43f2a562c84ff440da978a9275fc44e6f5d9da (diff) | |
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.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/attribute.h | 8 | ||||
| -rw-r--r-- | lib/dup2.c | 43 | ||||
| -rw-r--r-- | lib/fchmodat.c | 2 | ||||
| -rw-r--r-- | lib/fcntl.c | 87 | ||||
| -rw-r--r-- | lib/file-has-acl.c | 4 | ||||
| -rw-r--r-- | lib/free.c | 4 | ||||
| -rw-r--r-- | lib/getloadavg.c | 4 | ||||
| -rw-r--r-- | lib/gnulib.mk.in | 7 | ||||
| -rw-r--r-- | lib/issymlink.h | 46 | ||||
| -rw-r--r-- | lib/issymlinkat.c | 2 | ||||
| -rw-r--r-- | lib/issymlinkat.h | 68 | ||||
| -rw-r--r-- | lib/lchmod.c | 1 | ||||
| -rw-r--r-- | lib/realloc.c | 2 | ||||
| -rw-r--r-- | lib/str-two-way.h | 86 | ||||
| -rw-r--r-- | lib/string.in.h | 29 | ||||
| -rw-r--r-- | lib/time_rz.c | 4 |
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 |
