openat: don’t close (-1)
[gnulib.git] / lib / copy-file-range.c
blobe7e3a441c6b4b37b8f31c86047664f01d1d06664
1 /* Stub for copy_file_range
2 Copyright 2019-2024 Free Software Foundation, Inc.
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.
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.
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/>. */
17 #include <config.h>
19 #include <unistd.h>
21 #include <errno.h>
23 #if defined __linux__ && HAVE_COPY_FILE_RANGE
24 # include <sys/utsname.h>
25 #endif
27 ssize_t
28 copy_file_range (int infd, off_t *pinoff,
29 int outfd, off_t *poutoff,
30 size_t length, unsigned int flags)
32 #undef copy_file_range
34 #if defined __linux__ && HAVE_COPY_FILE_RANGE
35 /* The implementation of copy_file_range (which first appeared in
36 Linux kernel release 4.5) had many issues before release 5.3
37 <https://lwn.net/Articles/789527/>, so fail with ENOSYS for Linux
38 kernels 5.2 and earlier.
40 This workaround, and the configure-time check for Linux, can be
41 removed when such kernels (released March 2016 through September
42 2019) are no longer a consideration. As of January 2021, the
43 furthest-future planned kernel EOL is December 2024 for kernel
44 release 4.19. */
46 static signed char ok;
48 if (! ok)
50 struct utsname name;
51 uname (&name);
52 char *p = name.release;
53 ok = ((p[1] != '.' || '5' < p[0]
54 || (p[0] == '5' && (p[3] != '.' || '2' < p[2])))
55 ? 1 : -1);
58 if (0 < ok)
59 return copy_file_range (infd, pinoff, outfd, poutoff, length, flags);
60 #endif
62 /* There is little need to emulate copy_file_range with read+write,
63 since programs that use copy_file_range must fall back on
64 read+write anyway. */
65 errno = ENOSYS;
66 return -1;