diff options
| author | Paul Eggert | 2025-12-07 15:34:42 -0800 |
|---|---|---|
| committer | Paul Eggert | 2025-12-07 15:45:20 -0800 |
| commit | b211e5489b95f39f07baa769fc581b05b393c4a3 (patch) | |
| tree | 34f59c09f3779fdf25f32bccbe8aa48491ee5b4f /lib | |
| parent | 0d43f2a562c84ff440da978a9275fc44e6f5d9da (diff) | |
| download | emacs-b211e5489b95f39f07baa769fc581b05b393c4a3.tar.gz emacs-b211e5489b95f39f07baa769fc581b05b393c4a3.zip | |
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 @@ | |||
| 257 | calls to the function with the same arguments, so long as the state | 257 | calls to the function with the same arguments, so long as the state |
| 258 | addressed by its arguments is the same. | 258 | addressed by its arguments is the same. |
| 259 | This attribute is safe for a function that is effectless, idempotent, | 259 | This attribute is safe for a function that is effectless, idempotent, |
| 260 | stateless, and independent; see ISO C 23 § 6.7.12.7 for a definition of | 260 | stateless, and independent; see ISO C 23 § 6.7.13.8 for a definition of |
| 261 | these terms. | 261 | these terms. |
| 262 | (This attribute is stricter than REPRODUCIBLE because the function | 262 | (This attribute is stricter than REPRODUCIBLE because the function |
| 263 | must be stateless and independent. It is looser than ATTRIBUTE_CONST | 263 | must be stateless and independent. It is looser than ATTRIBUTE_CONST |
| @@ -266,7 +266,7 @@ | |||
| 266 | See also <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2956.htm> and | 266 | See also <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2956.htm> and |
| 267 | <https://stackoverflow.com/questions/76847905/>. | 267 | <https://stackoverflow.com/questions/76847905/>. |
| 268 | ATTENTION! Efforts are underway to change the meaning of this attribute. | 268 | ATTENTION! Efforts are underway to change the meaning of this attribute. |
| 269 | See <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3424.htm>. */ | 269 | See <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3494.htm>. */ |
| 270 | /* Applies to: functions, pointer to functions, function type. */ | 270 | /* Applies to: functions, pointer to functions, function type. */ |
| 271 | #define UNSEQUENCED _GL_ATTRIBUTE_UNSEQUENCED | 271 | #define UNSEQUENCED _GL_ATTRIBUTE_UNSEQUENCED |
| 272 | 272 | ||
| @@ -287,7 +287,7 @@ | |||
| 287 | addressed by its arguments is the same and is updated in time for | 287 | addressed by its arguments is the same and is updated in time for |
| 288 | the rest of the program. | 288 | the rest of the program. |
| 289 | This attribute is safe for a function that is effectless and idempotent; see | 289 | This attribute is safe for a function that is effectless and idempotent; see |
| 290 | ISO C 23 § 6.7.12.7 for a definition of these terms. | 290 | ISO C 23 § 6.7.13.8 for a definition of these terms. |
| 291 | (This attribute is looser than UNSEQUENCED because the function need | 291 | (This attribute is looser than UNSEQUENCED because the function need |
| 292 | not be stateless and idempotent. It is looser than ATTRIBUTE_PURE | 292 | not be stateless and idempotent. It is looser than ATTRIBUTE_PURE |
| 293 | because the function need not return exactly once and can affect | 293 | because the function need not return exactly once and can affect |
| @@ -295,7 +295,7 @@ | |||
| 295 | See also <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2956.htm> and | 295 | See also <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2956.htm> and |
| 296 | <https://stackoverflow.com/questions/76847905/>. | 296 | <https://stackoverflow.com/questions/76847905/>. |
| 297 | ATTENTION! Efforts are underway to change the meaning of this attribute. | 297 | ATTENTION! Efforts are underway to change the meaning of this attribute. |
| 298 | See <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3424.htm>. */ | 298 | See <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3494.htm>. */ |
| 299 | /* Applies to: functions, pointer to functions, function type. */ | 299 | /* Applies to: functions, pointer to functions, function type. */ |
| 300 | #define REPRODUCIBLE _GL_ATTRIBUTE_REPRODUCIBLE | 300 | #define REPRODUCIBLE _GL_ATTRIBUTE_REPRODUCIBLE |
| 301 | 301 | ||
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) | |||
| 114 | int dupfd; | 114 | int dupfd; |
| 115 | 115 | ||
| 116 | tempfd = open ("NUL", O_RDONLY); | 116 | tempfd = open ("NUL", O_RDONLY); |
| 117 | if (tempfd == -1) | 117 | if (tempfd < 0) |
| 118 | return -1; | 118 | return tempfd; |
| 119 | 119 | ||
| 120 | if (tempfd == desired_fd) | 120 | if (tempfd >= desired_fd) |
| 121 | { | 121 | { |
| 122 | close (tempfd); | 122 | close (tempfd); |
| 123 | 123 | ||
| @@ -125,7 +125,29 @@ klibc_dup2dirfd (int fd, int desired_fd) | |||
| 125 | if (__libc_Back_ioFHToPath (fd, path, sizeof (path))) | 125 | if (__libc_Back_ioFHToPath (fd, path, sizeof (path))) |
| 126 | return -1; | 126 | return -1; |
| 127 | 127 | ||
| 128 | return open(path, O_RDONLY); | 128 | for (;;) |
| 129 | { | ||
| 130 | close (desired_fd); | ||
| 131 | |||
| 132 | dupfd = open (path, O_RDONLY); | ||
| 133 | if (dupfd < 0) | ||
| 134 | return dupfd; | ||
| 135 | |||
| 136 | if (dupfd == desired_fd) | ||
| 137 | return dupfd; | ||
| 138 | |||
| 139 | /* If lower FD was closed by other threads, fill again. */ | ||
| 140 | if (dupfd < desired_fd) | ||
| 141 | { | ||
| 142 | tempfd = dupfd; | ||
| 143 | break; | ||
| 144 | } | ||
| 145 | |||
| 146 | /* desired_fd was opened by other threads. Try again. */ | ||
| 147 | /* FIXME: Closing desired_fd opened by other threads may lead to | ||
| 148 | unexpected behavior. */ | ||
| 149 | close (dupfd); | ||
| 150 | } | ||
| 129 | } | 151 | } |
| 130 | 152 | ||
| 131 | dupfd = klibc_dup2dirfd (fd, desired_fd); | 153 | dupfd = klibc_dup2dirfd (fd, desired_fd); |
| @@ -142,13 +164,9 @@ klibc_dup2 (int fd, int desired_fd) | |||
| 142 | struct stat sbuf; | 164 | struct stat sbuf; |
| 143 | 165 | ||
| 144 | dupfd = dup2 (fd, desired_fd); | 166 | dupfd = dup2 (fd, desired_fd); |
| 145 | if (dupfd == -1 && errno == ENOTSUP \ | 167 | if (dupfd < 0 && errno == ENOTSUP \ |
| 146 | && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode)) | 168 | && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode)) |
| 147 | { | 169 | return klibc_dup2dirfd (fd, desired_fd); |
| 148 | close (desired_fd); | ||
| 149 | |||
| 150 | return klibc_dup2dirfd (fd, desired_fd); | ||
| 151 | } | ||
| 152 | 170 | ||
| 153 | return dupfd; | 171 | return dupfd; |
| 154 | } | 172 | } |
| @@ -179,10 +197,11 @@ rpl_dup2 (int fd, int desired_fd) | |||
| 179 | result = dup2 (fd, desired_fd); | 197 | result = dup2 (fd, desired_fd); |
| 180 | 198 | ||
| 181 | /* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x. */ | 199 | /* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x. */ |
| 182 | if (result == -1 && errno == EMFILE) | 200 | if (result < 0 && errno == EMFILE) |
| 183 | errno = EBADF; | 201 | errno = EBADF; |
| 202 | |||
| 184 | #if REPLACE_FCHDIR | 203 | #if REPLACE_FCHDIR |
| 185 | if (fd != desired_fd && result != -1) | 204 | if (! (result < 0 || fd == desired_fd)) |
| 186 | result = _gl_register_dup (fd, result); | 205 | result = _gl_register_dup (fd, result); |
| 187 | #endif | 206 | #endif |
| 188 | return result; | 207 | 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) | |||
| 46 | 46 | ||
| 47 | #include <intprops.h> | 47 | #include <intprops.h> |
| 48 | 48 | ||
| 49 | #include "issymlink.h" | 49 | #include "issymlinkat.h" |
| 50 | 50 | ||
| 51 | /* Invoke chmod or lchmod on FILE, using mode MODE, in the directory | 51 | /* Invoke chmod or lchmod on FILE, using mode MODE, in the directory |
| 52 | open on descriptor FD. If possible, do it without changing the | 52 | 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 @@ | |||
| 29 | #include <unistd.h> | 29 | #include <unistd.h> |
| 30 | 30 | ||
| 31 | #ifdef __KLIBC__ | 31 | #ifdef __KLIBC__ |
| 32 | # define INCL_DOS | 32 | # include <emx/io.h> |
| 33 | # include <os2.h> | 33 | # include <InnoTekLIBC/backend.h> |
| 34 | #endif | 34 | #endif |
| 35 | 35 | ||
| 36 | #if defined _WIN32 && ! defined __CYGWIN__ | 36 | #if defined _WIN32 && ! defined __CYGWIN__ |
| @@ -539,6 +539,41 @@ rpl_fcntl_DUPFD_CLOEXEC (int fd, int target) | |||
| 539 | #undef fcntl | 539 | #undef fcntl |
| 540 | 540 | ||
| 541 | #ifdef __KLIBC__ | 541 | #ifdef __KLIBC__ |
| 542 | static int | ||
| 543 | klibc_dupdirfd (int fd, int minfd) | ||
| 544 | { | ||
| 545 | int tempfd; | ||
| 546 | int dupfd; | ||
| 547 | |||
| 548 | tempfd = open ("NUL", O_RDONLY); | ||
| 549 | if (tempfd == -1) | ||
| 550 | return -1; | ||
| 551 | |||
| 552 | if (tempfd >= minfd) | ||
| 553 | { | ||
| 554 | close (tempfd); | ||
| 555 | |||
| 556 | char path[_MAX_PATH]; | ||
| 557 | if (__libc_Back_ioFHToPath (fd, path, sizeof (path))) | ||
| 558 | return -1; | ||
| 559 | |||
| 560 | dupfd = open (path, O_RDONLY); | ||
| 561 | if (dupfd == -1) | ||
| 562 | return -1; | ||
| 563 | |||
| 564 | if (dupfd >= minfd) | ||
| 565 | return dupfd; | ||
| 566 | |||
| 567 | /* Lower FD was closed by other threads. Fill again. */ | ||
| 568 | tempfd = dupfd; | ||
| 569 | } | ||
| 570 | |||
| 571 | dupfd = klibc_dupdirfd (fd, minfd); | ||
| 572 | |||
| 573 | close (tempfd); | ||
| 574 | |||
| 575 | return dupfd; | ||
| 576 | } | ||
| 542 | 577 | ||
| 543 | static int | 578 | static int |
| 544 | klibc_fcntl (int fd, int action, /* arg */...) | 579 | klibc_fcntl (int fd, int action, /* arg */...) |
| @@ -555,46 +590,50 @@ klibc_fcntl (int fd, int action, /* arg */...) | |||
| 555 | if (result == -1 && (errno == EPERM || errno == ENOTSUP) | 590 | if (result == -1 && (errno == EPERM || errno == ENOTSUP) |
| 556 | && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode)) | 591 | && !fstat (fd, &sbuf) && S_ISDIR (sbuf.st_mode)) |
| 557 | { | 592 | { |
| 558 | ULONG ulMode; | 593 | PLIBCFH pFH; |
| 594 | unsigned fFlags; | ||
| 559 | 595 | ||
| 560 | switch (action) | 596 | switch (action) |
| 561 | { | 597 | { |
| 562 | case F_DUPFD: | 598 | case F_DUPFD: |
| 563 | /* Find available fd */ | 599 | result = klibc_dupdirfd (fd, arg); |
| 564 | while (fcntl (arg, F_GETFL) != -1 || errno != EBADF) | ||
| 565 | arg++; | ||
| 566 | |||
| 567 | result = dup2 (fd, arg); | ||
| 568 | break; | 600 | break; |
| 569 | 601 | ||
| 570 | /* Using underlying APIs is right ? */ | ||
| 571 | case F_GETFD: | 602 | case F_GETFD: |
| 572 | if (DosQueryFHState (fd, &ulMode)) | 603 | pFH = __libc_FH (fd); |
| 573 | break; | 604 | if (!pFH) |
| 605 | { | ||
| 606 | errno = EBADF; | ||
| 607 | break; | ||
| 608 | } | ||
| 574 | 609 | ||
| 575 | result = (ulMode & OPEN_FLAGS_NOINHERIT) ? FD_CLOEXEC : 0; | 610 | result = (pFH->fFlags & ((FD_CLOEXEC << __LIBC_FH_FDFLAGS_SHIFT ) |
| 611 | | O_NOINHERIT)) ? FD_CLOEXEC : 0; | ||
| 576 | break; | 612 | break; |
| 577 | 613 | ||
| 578 | case F_SETFD: | 614 | case F_SETFD: |
| 579 | if (arg & ~FD_CLOEXEC) | 615 | if (arg & ~FD_CLOEXEC) |
| 580 | break; | 616 | break; |
| 581 | 617 | ||
| 582 | if (DosQueryFHState (fd, &ulMode)) | 618 | pFH = __libc_FH (fd); |
| 583 | break; | 619 | if (!pFH) |
| 620 | { | ||
| 621 | errno = EBADF; | ||
| 622 | break; | ||
| 623 | } | ||
| 584 | 624 | ||
| 625 | fFlags = pFH->fFlags; | ||
| 585 | if (arg & FD_CLOEXEC) | 626 | if (arg & FD_CLOEXEC) |
| 586 | ulMode |= OPEN_FLAGS_NOINHERIT; | 627 | fFlags |= (FD_CLOEXEC << __LIBC_FH_FDFLAGS_SHIFT) | O_NOINHERIT; |
| 587 | else | 628 | else |
| 588 | ulMode &= ~OPEN_FLAGS_NOINHERIT; | 629 | fFlags &= ~((FD_CLOEXEC << __LIBC_FH_FDFLAGS_SHIFT) | O_NOINHERIT); |
| 589 | 630 | ||
| 590 | /* Filter supported flags. */ | 631 | result = __libc_FHSetFlags (pFH, fd, fFlags); |
| 591 | ulMode &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR | 632 | if (result < 0) |
| 592 | | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT); | 633 | { |
| 593 | 634 | errno = -result; | |
| 594 | if (DosSetFHState (fd, ulMode)) | 635 | result = -1; |
| 595 | break; | 636 | } |
| 596 | |||
| 597 | result = 0; | ||
| 598 | break; | 637 | break; |
| 599 | 638 | ||
| 600 | case F_GETFL: | 639 | 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) | |||
| 399 | if (fd < 0) | 399 | if (fd < 0) |
| 400 | return NULL; | 400 | return NULL; |
| 401 | acl_t r = acl_get_fd (fd); | 401 | acl_t r = acl_get_fd (fd); |
| 402 | int err = errno; | 402 | int saved_errno = errno; |
| 403 | close (fd); | 403 | close (fd); |
| 404 | errno = err; | 404 | errno = saved_errno; |
| 405 | return r; | 405 | return r; |
| 406 | } | 406 | } |
| 407 | # define HAVE_ACL_GET_LINK_NP 1 | 407 | # 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) | |||
| 44 | free (p); | 44 | free (p); |
| 45 | errno = err[errno == 0]; | 45 | errno = err[errno == 0]; |
| 46 | # else | 46 | # else |
| 47 | int err = errno; | 47 | int saved_errno = errno; |
| 48 | free (p); | 48 | free (p); |
| 49 | errno = err; | 49 | errno = saved_errno; |
| 50 | # endif | 50 | # endif |
| 51 | } | 51 | } |
| 52 | 52 | ||
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) | |||
| 551 | if (fd < 0) | 551 | if (fd < 0) |
| 552 | return fd; | 552 | return fd; |
| 553 | int nread = read (fd, readbuf, sizeof readbuf - 1); | 553 | int nread = read (fd, readbuf, sizeof readbuf - 1); |
| 554 | int err = errno; | 554 | int saved_errno = errno; |
| 555 | close (fd); | 555 | close (fd); |
| 556 | if (nread < 0) | 556 | if (nread < 0) |
| 557 | { | 557 | { |
| 558 | errno = err; | 558 | errno = saved_errno; |
| 559 | return -1; | 559 | return -1; |
| 560 | } | 560 | } |
| 561 | readbuf[nread] = '\0'; | 561 | 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 @@ | |||
| 71 | # --avoid=stat \ | 71 | # --avoid=stat \ |
| 72 | # --avoid=std-gnu11 \ | 72 | # --avoid=std-gnu11 \ |
| 73 | # --avoid=stdarg-h \ | 73 | # --avoid=stdarg-h \ |
| 74 | # --avoid=strncpy \ | ||
| 74 | # --avoid=threadlib \ | 75 | # --avoid=threadlib \ |
| 75 | # --avoid=tzset \ | 76 | # --avoid=tzset \ |
| 76 | # --avoid=unsetenv \ | 77 | # --avoid=unsetenv \ |
| @@ -631,6 +632,7 @@ GL_GNULIB_STRERROR_R = @GL_GNULIB_STRERROR_R@ | |||
| 631 | GL_GNULIB_STRFTIME = @GL_GNULIB_STRFTIME@ | 632 | GL_GNULIB_STRFTIME = @GL_GNULIB_STRFTIME@ |
| 632 | GL_GNULIB_STRINGEQ = @GL_GNULIB_STRINGEQ@ | 633 | GL_GNULIB_STRINGEQ = @GL_GNULIB_STRINGEQ@ |
| 633 | GL_GNULIB_STRNCAT = @GL_GNULIB_STRNCAT@ | 634 | GL_GNULIB_STRNCAT = @GL_GNULIB_STRNCAT@ |
| 635 | GL_GNULIB_STRNCPY = @GL_GNULIB_STRNCPY@ | ||
| 634 | GL_GNULIB_STRNDUP = @GL_GNULIB_STRNDUP@ | 636 | GL_GNULIB_STRNDUP = @GL_GNULIB_STRNDUP@ |
| 635 | GL_GNULIB_STRNLEN = @GL_GNULIB_STRNLEN@ | 637 | GL_GNULIB_STRNLEN = @GL_GNULIB_STRNLEN@ |
| 636 | GL_GNULIB_STRPBRK = @GL_GNULIB_STRPBRK@ | 638 | GL_GNULIB_STRPBRK = @GL_GNULIB_STRPBRK@ |
| @@ -1327,6 +1329,7 @@ REPLACE_STRERROR_L = @REPLACE_STRERROR_L@ | |||
| 1327 | REPLACE_STRERROR_R = @REPLACE_STRERROR_R@ | 1329 | REPLACE_STRERROR_R = @REPLACE_STRERROR_R@ |
| 1328 | REPLACE_STRFTIME = @REPLACE_STRFTIME@ | 1330 | REPLACE_STRFTIME = @REPLACE_STRFTIME@ |
| 1329 | REPLACE_STRNCAT = @REPLACE_STRNCAT@ | 1331 | REPLACE_STRNCAT = @REPLACE_STRNCAT@ |
| 1332 | REPLACE_STRNCPY = @REPLACE_STRNCPY@ | ||
| 1330 | REPLACE_STRNDUP = @REPLACE_STRNDUP@ | 1333 | REPLACE_STRNDUP = @REPLACE_STRNDUP@ |
| 1331 | REPLACE_STRNLEN = @REPLACE_STRNLEN@ | 1334 | REPLACE_STRNLEN = @REPLACE_STRNLEN@ |
| 1332 | REPLACE_STRSIGNAL = @REPLACE_STRSIGNAL@ | 1335 | REPLACE_STRSIGNAL = @REPLACE_STRSIGNAL@ |
| @@ -2650,7 +2653,7 @@ ifneq (,$(gl_GNULIB_ENABLED_issymlinkat_CONDITION)) | |||
| 2650 | libgnu_a_SOURCES += issymlinkat.c | 2653 | libgnu_a_SOURCES += issymlinkat.c |
| 2651 | 2654 | ||
| 2652 | endif | 2655 | endif |
| 2653 | EXTRA_DIST += issymlink.h | 2656 | EXTRA_DIST += issymlinkat.h |
| 2654 | 2657 | ||
| 2655 | endif | 2658 | endif |
| 2656 | ## end gnulib module issymlinkat | 2659 | ## end gnulib module issymlinkat |
| @@ -3757,6 +3760,7 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H | |||
| 3757 | -e 's/@''GNULIB_STRDUP''@/$(GL_GNULIB_STRDUP)/g' \ | 3760 | -e 's/@''GNULIB_STRDUP''@/$(GL_GNULIB_STRDUP)/g' \ |
| 3758 | -e 's/@''GNULIB_STRINGEQ''@/$(GL_GNULIB_STRINGEQ)/g' \ | 3761 | -e 's/@''GNULIB_STRINGEQ''@/$(GL_GNULIB_STRINGEQ)/g' \ |
| 3759 | -e 's/@''GNULIB_STRNCAT''@/$(GL_GNULIB_STRNCAT)/g' \ | 3762 | -e 's/@''GNULIB_STRNCAT''@/$(GL_GNULIB_STRNCAT)/g' \ |
| 3763 | -e 's/@''GNULIB_STRNCPY''@/$(GL_GNULIB_STRNCPY)/g' \ | ||
| 3760 | -e 's/@''GNULIB_STRNDUP''@/$(GL_GNULIB_STRNDUP)/g' \ | 3764 | -e 's/@''GNULIB_STRNDUP''@/$(GL_GNULIB_STRNDUP)/g' \ |
| 3761 | -e 's/@''GNULIB_STRNLEN''@/$(GL_GNULIB_STRNLEN)/g' \ | 3765 | -e 's/@''GNULIB_STRNLEN''@/$(GL_GNULIB_STRNLEN)/g' \ |
| 3762 | -e 's/@''GNULIB_STRPBRK''@/$(GL_GNULIB_STRPBRK)/g' \ | 3766 | -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 | |||
| 3818 | -e 's|@''REPLACE_STRCHRNUL''@|$(REPLACE_STRCHRNUL)|g' \ | 3822 | -e 's|@''REPLACE_STRCHRNUL''@|$(REPLACE_STRCHRNUL)|g' \ |
| 3819 | -e 's|@''REPLACE_STRDUP''@|$(REPLACE_STRDUP)|g' \ | 3823 | -e 's|@''REPLACE_STRDUP''@|$(REPLACE_STRDUP)|g' \ |
| 3820 | -e 's|@''REPLACE_STRNCAT''@|$(REPLACE_STRNCAT)|g' \ | 3824 | -e 's|@''REPLACE_STRNCAT''@|$(REPLACE_STRNCAT)|g' \ |
| 3825 | -e 's|@''REPLACE_STRNCPY''@|$(REPLACE_STRNCPY)|g' \ | ||
| 3821 | -e 's|@''REPLACE_STRNDUP''@|$(REPLACE_STRNDUP)|g' \ | 3826 | -e 's|@''REPLACE_STRNDUP''@|$(REPLACE_STRNDUP)|g' \ |
| 3822 | -e 's|@''REPLACE_STRNLEN''@|$(REPLACE_STRNLEN)|g' \ | 3827 | -e 's|@''REPLACE_STRNLEN''@|$(REPLACE_STRNLEN)|g' \ |
| 3823 | -e 's|@''REPLACE_STRSTR''@|$(REPLACE_STRSTR)|g' \ | 3828 | -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 @@ | |||
| 23 | #endif | 23 | #endif |
| 24 | 24 | ||
| 25 | #include <errno.h> | 25 | #include <errno.h> |
| 26 | #include <unistd.h> /* for readlink, readlinkat */ | 26 | #include <unistd.h> /* for readlink */ |
| 27 | 27 | ||
| 28 | 28 | ||
| 29 | _GL_INLINE_HEADER_BEGIN | 29 | _GL_INLINE_HEADER_BEGIN |
| @@ -31,11 +31,7 @@ _GL_INLINE_HEADER_BEGIN | |||
| 31 | #ifndef _GL_ISSYMLINK_INLINE | 31 | #ifndef _GL_ISSYMLINK_INLINE |
| 32 | # define _GL_ISSYMLINK_INLINE _GL_INLINE | 32 | # define _GL_ISSYMLINK_INLINE _GL_INLINE |
| 33 | #endif | 33 | #endif |
| 34 | #ifndef _GL_ISSYMLINKAT_INLINE | ||
| 35 | # define _GL_ISSYMLINKAT_INLINE _GL_INLINE | ||
| 36 | #endif | ||
| 37 | 34 | ||
| 38 | #if GNULIB_ISSYMLINK | ||
| 39 | /* Tests whether FILENAME represents a symbolic link. | 35 | /* Tests whether FILENAME represents a symbolic link. |
| 40 | This function is more reliable than lstat() / fstatat() followed by S_ISLNK, | 36 | This function is more reliable than lstat() / fstatat() followed by S_ISLNK, |
| 41 | because it avoids possible EOVERFLOW errors. | 37 | because it avoids possible EOVERFLOW errors. |
| @@ -44,9 +40,9 @@ _GL_INLINE_HEADER_BEGIN | |||
| 44 | 0 if FILENAME exists and is not a symbolic link, | 40 | 0 if FILENAME exists and is not a symbolic link, |
| 45 | -1 with errno set if determination failed, in particular | 41 | -1 with errno set if determination failed, in particular |
| 46 | -1 with errno = ENOENT or ENOTDIR if FILENAME does not exist. */ | 42 | -1 with errno = ENOENT or ENOTDIR if FILENAME does not exist. */ |
| 47 | # ifdef __cplusplus | 43 | #ifdef __cplusplus |
| 48 | extern "C" { | 44 | extern "C" { |
| 49 | # endif | 45 | #endif |
| 50 | _GL_ISSYMLINK_INLINE int issymlink (const char *filename) | 46 | _GL_ISSYMLINK_INLINE int issymlink (const char *filename) |
| 51 | _GL_ARG_NONNULL ((1)); | 47 | _GL_ARG_NONNULL ((1)); |
| 52 | _GL_ISSYMLINK_INLINE int | 48 | _GL_ISSYMLINK_INLINE int |
| @@ -60,42 +56,8 @@ issymlink (const char *filename) | |||
| 60 | else | 56 | else |
| 61 | return -1; | 57 | return -1; |
| 62 | } | 58 | } |
| 63 | # ifdef __cplusplus | 59 | #ifdef __cplusplus |
| 64 | } | ||
| 65 | # endif | ||
| 66 | #endif | ||
| 67 | |||
| 68 | #if GNULIB_ISSYMLINKAT | ||
| 69 | /* Tests whether FILENAME represents a symbolic link. | ||
| 70 | This function is more reliable than lstat() / fstatat() followed by S_ISLNK, | ||
| 71 | because it avoids possible EOVERFLOW errors. | ||
| 72 | If FILENAME is a relative file name, it is interpreted as relative to the | ||
| 73 | directory referred to by FD (where FD = AT_FDCWD denotes the current | ||
| 74 | directory). | ||
| 75 | Returns | ||
| 76 | 1 if FILENAME is a symbolic link, | ||
| 77 | 0 if FILENAME exists and is not a symbolic link, | ||
| 78 | -1 with errno set if determination failed, in particular | ||
| 79 | -1 with errno = ENOENT or ENOTDIR if FILENAME does not exist. */ | ||
| 80 | # ifdef __cplusplus | ||
| 81 | extern "C" { | ||
| 82 | # endif | ||
| 83 | _GL_ISSYMLINKAT_INLINE int issymlinkat (int fd, const char *filename) | ||
| 84 | _GL_ARG_NONNULL ((2)); | ||
| 85 | _GL_ISSYMLINKAT_INLINE int | ||
| 86 | issymlinkat (int fd, const char *filename) | ||
| 87 | { | ||
| 88 | char linkbuf[1]; | ||
| 89 | if (readlinkat (fd, filename, linkbuf, sizeof (linkbuf)) >= 0) | ||
| 90 | return 1; | ||
| 91 | if (errno == EINVAL) | ||
| 92 | return 0; | ||
| 93 | else | ||
| 94 | return -1; | ||
| 95 | } | ||
| 96 | # ifdef __cplusplus | ||
| 97 | } | 60 | } |
| 98 | # endif | ||
| 99 | #endif | 61 | #endif |
| 100 | 62 | ||
| 101 | _GL_INLINE_HEADER_END | 63 | _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 @@ | |||
| 17 | #include <config.h> | 17 | #include <config.h> |
| 18 | 18 | ||
| 19 | #define _GL_ISSYMLINKAT_INLINE _GL_EXTERN_INLINE | 19 | #define _GL_ISSYMLINKAT_INLINE _GL_EXTERN_INLINE |
| 20 | #include "issymlink.h" | 20 | #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 @@ | |||
| 1 | /* Test whether a file is a symbolic link. | ||
| 2 | Copyright (C) 2025 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | This file is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU Lesser General Public License as | ||
| 6 | published by the Free Software Foundation; either version 2.1 of the | ||
| 7 | License, or (at your option) any later version. | ||
| 8 | |||
| 9 | This file is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU Lesser General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU Lesser General Public License | ||
| 15 | along with this program. If not, see <https://www.gnu.org/licenses/>. */ | ||
| 16 | |||
| 17 | #ifndef _ISSYMLINKAT_H | ||
| 18 | #define _ISSYMLINKAT_H | ||
| 19 | |||
| 20 | /* This file uses _GL_ARG_NONNULL, _GL_INLINE. */ | ||
| 21 | #if !_GL_CONFIG_H_INCLUDED | ||
| 22 | #error "Please include config.h first." | ||
| 23 | #endif | ||
| 24 | |||
| 25 | #include <errno.h> | ||
| 26 | #include <unistd.h> /* for readlinkat */ | ||
| 27 | |||
| 28 | |||
| 29 | _GL_INLINE_HEADER_BEGIN | ||
| 30 | |||
| 31 | #ifndef _GL_ISSYMLINKAT_INLINE | ||
| 32 | # define _GL_ISSYMLINKAT_INLINE _GL_INLINE | ||
| 33 | #endif | ||
| 34 | |||
| 35 | /* Tests whether FILENAME represents a symbolic link. | ||
| 36 | This function is more reliable than lstat() / fstatat() followed by S_ISLNK, | ||
| 37 | because it avoids possible EOVERFLOW errors. | ||
| 38 | If FILENAME is a relative file name, it is interpreted as relative to the | ||
| 39 | directory referred to by FD (where FD = AT_FDCWD denotes the current | ||
| 40 | directory). | ||
| 41 | Returns | ||
| 42 | 1 if FILENAME is a symbolic link, | ||
| 43 | 0 if FILENAME exists and is not a symbolic link, | ||
| 44 | -1 with errno set if determination failed, in particular | ||
| 45 | -1 with errno = ENOENT or ENOTDIR if FILENAME does not exist. */ | ||
| 46 | #ifdef __cplusplus | ||
| 47 | extern "C" { | ||
| 48 | #endif | ||
| 49 | _GL_ISSYMLINKAT_INLINE int issymlinkat (int fd, const char *filename) | ||
| 50 | _GL_ARG_NONNULL ((2)); | ||
| 51 | _GL_ISSYMLINKAT_INLINE int | ||
| 52 | issymlinkat (int fd, const char *filename) | ||
| 53 | { | ||
| 54 | char linkbuf[1]; | ||
| 55 | if (readlinkat (fd, filename, linkbuf, sizeof (linkbuf)) >= 0) | ||
| 56 | return 1; | ||
| 57 | if (errno == EINVAL) | ||
| 58 | return 0; | ||
| 59 | else | ||
| 60 | return -1; | ||
| 61 | } | ||
| 62 | #ifdef __cplusplus | ||
| 63 | } | ||
| 64 | #endif | ||
| 65 | |||
| 66 | _GL_INLINE_HEADER_END | ||
| 67 | |||
| 68 | #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 @@ | |||
| 30 | 30 | ||
| 31 | #include <intprops.h> | 31 | #include <intprops.h> |
| 32 | #include "issymlink.h" | 32 | #include "issymlink.h" |
| 33 | #include "issymlinkat.h" | ||
| 33 | 34 | ||
| 34 | /* Work like chmod, except when FILE is a symbolic link. | 35 | /* Work like chmod, except when FILE is a symbolic link. |
| 35 | In that case, on systems where permissions on symbolic links are unsupported | 36 | 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) | |||
| 94 | 94 | ||
| 95 | void *result = realloc (p, n1); | 95 | void *result = realloc (p, n1); |
| 96 | 96 | ||
| 97 | # if !HAVE_MALLOC_POSIX | 97 | # if !HAVE_REALLOC_POSIX |
| 98 | if (result == NULL) | 98 | if (result == NULL) |
| 99 | errno = ENOMEM; | 99 | errno = ENOMEM; |
| 100 | # endif | 100 | # 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, | |||
| 374 | } | 374 | } |
| 375 | memory = 0; | 375 | memory = 0; |
| 376 | j += shift; | 376 | j += shift; |
| 377 | continue; | ||
| 378 | } | ||
| 379 | /* Scan for matches in right half. The last byte has | ||
| 380 | already been matched, by virtue of the shift table. */ | ||
| 381 | size_t i = MAX (suffix, memory); | ||
| 382 | while (i < needle_len - 1 && (CANON_ELEMENT (needle[i]) | ||
| 383 | == CANON_ELEMENT (haystack[i + j]))) | ||
| 384 | ++i; | ||
| 385 | if (needle_len - 1 <= i) | ||
| 386 | { | ||
| 387 | /* Scan for matches in left half. */ | ||
| 388 | i = suffix - 1; | ||
| 389 | while (memory < i + 1 && (CANON_ELEMENT (needle[i]) | ||
| 390 | == CANON_ELEMENT (haystack[i + j]))) | ||
| 391 | --i; | ||
| 392 | if (i + 1 < memory + 1) | ||
| 393 | return (RETURN_TYPE) (haystack + j); | ||
| 394 | /* No match, so remember how many repetitions of period | ||
| 395 | on the right half were scanned. */ | ||
| 396 | j += period; | ||
| 397 | memory = needle_len - period; | ||
| 398 | } | 377 | } |
| 399 | else | 378 | else |
| 400 | { | 379 | { |
| 401 | j += i - suffix + 1; | 380 | /* Scan for matches in right half. The last byte has |
| 402 | memory = 0; | 381 | already been matched, by virtue of the shift table. */ |
| 382 | size_t i = MAX (suffix, memory); | ||
| 383 | while (i < needle_len - 1 && (CANON_ELEMENT (needle[i]) | ||
| 384 | == CANON_ELEMENT (haystack[i + j]))) | ||
| 385 | ++i; | ||
| 386 | if (needle_len - 1 <= i) | ||
| 387 | { | ||
| 388 | /* Scan for matches in left half. */ | ||
| 389 | i = suffix - 1; | ||
| 390 | while (memory < i + 1 && (CANON_ELEMENT (needle[i]) | ||
| 391 | == CANON_ELEMENT (haystack[i + j]))) | ||
| 392 | --i; | ||
| 393 | if (i + 1 < memory + 1) | ||
| 394 | return (RETURN_TYPE) (haystack + j); | ||
| 395 | /* No match, so remember how many repetitions of period | ||
| 396 | on the right half were scanned. */ | ||
| 397 | j += period; | ||
| 398 | memory = needle_len - period; | ||
| 399 | } | ||
| 400 | else | ||
| 401 | { | ||
| 402 | j += i - suffix + 1; | ||
| 403 | memory = 0; | ||
| 404 | } | ||
| 403 | } | 405 | } |
| 404 | } | 406 | } |
| 405 | } | 407 | } |
| @@ -418,27 +420,29 @@ two_way_long_needle (const unsigned char *haystack, size_t haystack_len, | |||
| 418 | if (0 < shift) | 420 | if (0 < shift) |
| 419 | { | 421 | { |
| 420 | j += shift; | 422 | j += shift; |
| 421 | continue; | ||
| 422 | } | 423 | } |
| 423 | /* Scan for matches in right half. The last byte has | 424 | else |
| 424 | already been matched, by virtue of the shift table. */ | ||
| 425 | size_t i = suffix; | ||
| 426 | while (i < needle_len - 1 && (CANON_ELEMENT (needle[i]) | ||
| 427 | == CANON_ELEMENT (haystack[i + j]))) | ||
| 428 | ++i; | ||
| 429 | if (needle_len - 1 <= i) | ||
| 430 | { | 425 | { |
| 431 | /* Scan for matches in left half. */ | 426 | /* Scan for matches in right half. The last byte has |
| 432 | i = suffix - 1; | 427 | already been matched, by virtue of the shift table. */ |
| 433 | while (i != SIZE_MAX && (CANON_ELEMENT (needle[i]) | 428 | size_t i = suffix; |
| 434 | == CANON_ELEMENT (haystack[i + j]))) | 429 | while (i < needle_len - 1 && (CANON_ELEMENT (needle[i]) |
| 435 | --i; | 430 | == CANON_ELEMENT (haystack[i + j]))) |
| 436 | if (i == SIZE_MAX) | 431 | ++i; |
| 437 | return (RETURN_TYPE) (haystack + j); | 432 | if (needle_len - 1 <= i) |
| 438 | j += period; | 433 | { |
| 434 | /* Scan for matches in left half. */ | ||
| 435 | i = suffix - 1; | ||
| 436 | while (i != SIZE_MAX && (CANON_ELEMENT (needle[i]) | ||
| 437 | == CANON_ELEMENT (haystack[i + j]))) | ||
| 438 | --i; | ||
| 439 | if (i == SIZE_MAX) | ||
| 440 | return (RETURN_TYPE) (haystack + j); | ||
| 441 | j += period; | ||
| 442 | } | ||
| 443 | else | ||
| 444 | j += i - suffix + 1; | ||
| 439 | } | 445 | } |
| 440 | else | ||
| 441 | j += i - suffix + 1; | ||
| 442 | } | 446 | } |
| 443 | } | 447 | } |
| 444 | return NULL; | 448 | 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 - " | |||
| 840 | # endif | 840 | # endif |
| 841 | #endif | 841 | #endif |
| 842 | 842 | ||
| 843 | /* Copy no more than N bytes of SRC to DST, returning DST. */ | ||
| 844 | #if @GNULIB_STRNCPY@ | ||
| 845 | # if @REPLACE_STRNCPY@ | ||
| 846 | # if !(defined __cplusplus && defined GNULIB_NAMESPACE) | ||
| 847 | # undef strncpy | ||
| 848 | # define strncpy rpl_strncpy | ||
| 849 | # endif | ||
| 850 | _GL_FUNCDECL_RPL (strncpy, char *, | ||
| 851 | (char *restrict __dst, char const *restrict __src, | ||
| 852 | size_t __n), | ||
| 853 | _GL_ARG_NONNULL ((1, 2))); | ||
| 854 | _GL_CXXALIAS_RPL (strncpy, char *, | ||
| 855 | (char *restrict __dst, char const *restrict __src, | ||
| 856 | size_t __n)); | ||
| 857 | # else | ||
| 858 | _GL_CXXALIAS_SYS (strncpy, char *, | ||
| 859 | (char *restrict __dst, char const *restrict __src, | ||
| 860 | size_t __n)); | ||
| 861 | # endif | ||
| 862 | # if __GLIBC__ >= 2 | ||
| 863 | _GL_CXXALIASWARN (strncpy); | ||
| 864 | # endif | ||
| 865 | #elif defined GNULIB_POSIXCHECK | ||
| 866 | # if HAVE_RAW_DECL_STRNCPY | ||
| 867 | _GL_WARN_ON_USE (strncpy, "strncpy is unportable - " | ||
| 868 | "use gnulib module strncpy for portability"); | ||
| 869 | # endif | ||
| 870 | #endif | ||
| 871 | |||
| 843 | /* Return a newly allocated copy of at most N bytes of STRING. */ | 872 | /* Return a newly allocated copy of at most N bytes of STRING. */ |
| 844 | #if @GNULIB_STRNDUP@ | 873 | #if @GNULIB_STRNDUP@ |
| 845 | # if @REPLACE_STRNDUP@ | 874 | # 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 | |||
| 57 | tzfree (timezone_t tz) | 57 | tzfree (timezone_t tz) |
| 58 | # undef tzfree | 58 | # undef tzfree |
| 59 | { | 59 | { |
| 60 | int err = errno; | 60 | int saved_errno = errno; |
| 61 | tzfree (tz); | 61 | tzfree (tz); |
| 62 | errno = err; | 62 | errno = saved_errno; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | #else | 65 | #else |