diff options
| author | Paul Eggert | 2025-08-02 10:47:03 -0700 |
|---|---|---|
| committer | Paul Eggert | 2025-08-02 11:19:24 -0700 |
| commit | 687d3cb03bddd7eebf6384001fc54ca2c7e80037 (patch) | |
| tree | 664dbb5dbf966c72df4cd8dcc0567b501183f773 /lib | |
| parent | 84f1080f67c0960cca2d456c68e2d7866c19462c (diff) | |
| download | emacs-687d3cb03bddd7eebf6384001fc54ca2c7e80037.tar.gz emacs-687d3cb03bddd7eebf6384001fc54ca2c7e80037.zip | |
Update from Gnulib by running admin/merge-gnulib
* lib/sys-limits.h: New file.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/copy-file-range.c | 72 | ||||
| -rw-r--r-- | lib/gnulib.mk.in | 2 | ||||
| -rw-r--r-- | lib/sys-limits.h | 42 |
3 files changed, 96 insertions, 20 deletions
diff --git a/lib/copy-file-range.c b/lib/copy-file-range.c index 8e0c644c086..2465a558028 100644 --- a/lib/copy-file-range.c +++ b/lib/copy-file-range.c | |||
| @@ -21,9 +21,22 @@ | |||
| 21 | #include <errno.h> | 21 | #include <errno.h> |
| 22 | 22 | ||
| 23 | #if defined __linux__ && HAVE_COPY_FILE_RANGE | 23 | #if defined __linux__ && HAVE_COPY_FILE_RANGE |
| 24 | # include <linux/version.h> | ||
| 24 | # include <sys/utsname.h> | 25 | # include <sys/utsname.h> |
| 26 | /* Although it can be dicey to use static checks for Linux kernel versions, | ||
| 27 | due to the dubious practice of building on newer kernels for older ones, | ||
| 28 | do it here anyway as the buggy kernels are rare (they are all EOLed) | ||
| 29 | and builders for them are unlikely to use the dubious practice. | ||
| 30 | Circa 2029 we should remove the old-kernel workarounds entirely. */ | ||
| 31 | # if LINUX_VERSION_CODE < KERNEL_VERSION (5, 3, 0) | ||
| 32 | # define CHECK_LINUX_KERNEL_VERSION true | ||
| 33 | # else | ||
| 34 | # define CHECK_LINUX_KERNEL_VERSION false | ||
| 35 | # endif | ||
| 25 | #endif | 36 | #endif |
| 26 | 37 | ||
| 38 | #include "sys-limits.h" | ||
| 39 | |||
| 27 | ssize_t | 40 | ssize_t |
| 28 | copy_file_range (int infd, off_t *pinoff, | 41 | copy_file_range (int infd, off_t *pinoff, |
| 29 | int outfd, off_t *poutoff, | 42 | int outfd, off_t *poutoff, |
| @@ -31,32 +44,51 @@ copy_file_range (int infd, off_t *pinoff, | |||
| 31 | { | 44 | { |
| 32 | #undef copy_file_range | 45 | #undef copy_file_range |
| 33 | 46 | ||
| 34 | #if defined __linux__ && HAVE_COPY_FILE_RANGE | 47 | #if HAVE_COPY_FILE_RANGE |
| 48 | bool ok = true; | ||
| 49 | |||
| 50 | # if CHECK_LINUX_KERNEL_VERSION | ||
| 35 | /* The implementation of copy_file_range (which first appeared in | 51 | /* The implementation of copy_file_range (which first appeared in |
| 36 | Linux kernel release 4.5) had many issues before release 5.3 | 52 | Linux kernel release 4.5) had many issues before release 5.3 |
| 37 | <https://lwn.net/Articles/789527/>, so fail with ENOSYS for Linux | 53 | <https://lwn.net/Articles/789527/>, so fail with ENOSYS for Linux |
| 38 | kernels 5.2 and earlier. | 54 | kernels 5.2 and earlier. |
| 39 | 55 | ||
| 40 | This workaround, and the configure-time check for Linux, can be | 56 | This workaround can be removed when such kernels (released March |
| 41 | removed when such kernels (released March 2016 through September | 57 | 2016 through September 2019) are no longer a consideration. |
| 42 | 2019) are no longer a consideration. As of January 2021, the | 58 | Although all such kernels have reached EOL, some distros use |
| 43 | furthest-future planned kernel EOL is December 2024 for kernel | 59 | older kernels. For example, RHEL 8 uses kernel 4.18 and has an |
| 44 | release 4.19. */ | 60 | EOL of 2029. */ |
| 45 | 61 | ||
| 46 | static signed char ok; | 62 | static signed char kernel_ok; |
| 47 | 63 | if (! kernel_ok) | |
| 48 | if (! ok) | 64 | { |
| 49 | { | 65 | struct utsname name; |
| 50 | struct utsname name; | 66 | uname (&name); |
| 51 | uname (&name); | 67 | char *p = name.release; |
| 52 | char *p = name.release; | 68 | kernel_ok = ((p[1] != '.' || '5' < p[0] |
| 53 | ok = ((p[1] != '.' || '5' < p[0] | 69 | || (p[0] == '5' && (p[3] != '.' || '2' < p[2]))) |
| 54 | || (p[0] == '5' && (p[3] != '.' || '2' < p[2]))) | 70 | ? 1 : -1); |
| 55 | ? 1 : -1); | 71 | } |
| 56 | } | 72 | |
| 57 | 73 | if (kernel_ok < 0) | |
| 58 | if (0 < ok) | 74 | ok = false; |
| 75 | # endif | ||
| 76 | |||
| 77 | if (ok) | ||
| 78 | { | ||
| 79 | # if defined __GLIBC__ && ! (2 < __GLIBC__ + (43 <= __GLIBC_MINOR__)) | ||
| 80 | /* Work around glibc bug 33245 | ||
| 81 | <https://sourceware.org/bugzilla/show_bug.cgi?id=33245>. | ||
| 82 | This bug is present in glibc 2.42 (2025) and fixed in 2.43, | ||
| 83 | so this workaround, and the configure-time check for glibc, | ||
| 84 | can be removed once glibc 2.42 and earlier is no longer a | ||
| 85 | consideration. Perhaps in 2040. */ | ||
| 86 | if (SYS_BUFSIZE_MAX < length) | ||
| 87 | length = SYS_BUFSIZE_MAX; | ||
| 88 | # endif | ||
| 89 | |||
| 59 | return copy_file_range (infd, pinoff, outfd, poutoff, length, flags); | 90 | return copy_file_range (infd, pinoff, outfd, poutoff, length, flags); |
| 91 | } | ||
| 60 | #endif | 92 | #endif |
| 61 | 93 | ||
| 62 | /* There is little need to emulate copy_file_range with read+write, | 94 | /* There is little need to emulate copy_file_range with read+write, |
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index b3774a648b8..fa800300a42 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in | |||
| @@ -1799,6 +1799,8 @@ ifneq (,$(GL_COND_OBJ_COPY_FILE_RANGE_CONDITION)) | |||
| 1799 | libgnu_a_SOURCES += copy-file-range.c | 1799 | libgnu_a_SOURCES += copy-file-range.c |
| 1800 | endif | 1800 | endif |
| 1801 | 1801 | ||
| 1802 | EXTRA_DIST += sys-limits.h | ||
| 1803 | |||
| 1802 | endif | 1804 | endif |
| 1803 | ## end gnulib module copy-file-range | 1805 | ## end gnulib module copy-file-range |
| 1804 | 1806 | ||
diff --git a/lib/sys-limits.h b/lib/sys-limits.h new file mode 100644 index 00000000000..a556dfeb6d5 --- /dev/null +++ b/lib/sys-limits.h | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | /* System call limits | ||
| 2 | |||
| 3 | Copyright 2018-2025 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | This file is free software: you can redistribute it and/or modify | ||
| 6 | it under the terms of the GNU Lesser General Public License as | ||
| 7 | published by the Free Software Foundation; either version 2.1 of the | ||
| 8 | License, or (at your option) any later version. | ||
| 9 | |||
| 10 | This file is distributed in the hope that it will be useful, | ||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | GNU Lesser General Public License for more details. | ||
| 14 | |||
| 15 | You should have received a copy of the GNU Lesser General Public License | ||
| 16 | along with this program. If not, see <https://www.gnu.org/licenses/>. */ | ||
| 17 | |||
| 18 | #ifndef _GL_SYS_LIMITS_H | ||
| 19 | #define _GL_SYS_LIMITS_H | ||
| 20 | |||
| 21 | #include <limits.h> | ||
| 22 | |||
| 23 | /* Maximum number of bytes to read or write in a single system call. | ||
| 24 | This can be useful for system calls like sendfile on GNU/Linux, | ||
| 25 | which do not handle more than MAX_RW_COUNT bytes correctly. | ||
| 26 | The Linux kernel MAX_RW_COUNT is at least INT_MAX >> 20 << 20, | ||
| 27 | where the 20 comes from the Hexagon port with 1 MiB pages; use that | ||
| 28 | as an approximation, as the exact value may not be available to us. | ||
| 29 | |||
| 30 | Using this also works around a serious Linux bug before 2.6.16; see | ||
| 31 | <https://bugzilla.redhat.com/show_bug.cgi?id=612839>. | ||
| 32 | |||
| 33 | Using this also works around a Tru64 5.1 bug, where attempting | ||
| 34 | to read INT_MAX bytes fails with errno == EINVAL. See | ||
| 35 | <https://lists.gnu.org/r/bug-gnu-utils/2002-04/msg00010.html>. | ||
| 36 | |||
| 37 | Using this is likely to work around similar bugs in other operating | ||
| 38 | systems. */ | ||
| 39 | |||
| 40 | enum { SYS_BUFSIZE_MAX = INT_MAX >> 20 << 20 }; | ||
| 41 | |||
| 42 | #endif | ||