[scan] Fix for platforms without fcopyfile() or copy_file_range()

Add @cagney's fallback copy function. Use feature tests in configure.ac for
fcopyfile() and copy_file_range().

Fixes #1901
This commit is contained in:
ejurgensen 2025-07-27 22:40:33 +02:00
parent 6a21cad6fd
commit 7b91d43274
2 changed files with 28 additions and 5 deletions

View File

@ -96,7 +96,13 @@ AC_SEARCH_LIBS([pthread_getthreadid_np], [pthread],
[Define to 1 if you have pthread_getthreadid_np])]) [Define to 1 if you have pthread_getthreadid_np])])
AC_SEARCH_LIBS([uuid_generate_random], [uuid], AC_SEARCH_LIBS([uuid_generate_random], [uuid],
[AC_DEFINE([HAVE_UUID], 1, [AC_DEFINE([HAVE_UUID], 1,
[Define to 1 if you have uuid_generate_random function])]) [Define to 1 if you have uuid_generate_random])])
AC_SEARCH_LIBS([copy_file_range], [c],
[AC_DEFINE([HAVE_COPY_FILE_RANGE], 1,
[Define to 1 if you have copy_file_range])])
AC_SEARCH_LIBS([fcopyfile], [c],
[AC_DEFINE([HAVE_FCOPYFILE], 1,
[Define to 1 if you have fcopyfile])])
AC_SEARCH_LIBS([log10], [m]) AC_SEARCH_LIBS([log10], [m])
AC_SEARCH_LIBS([lrint], [m]) AC_SEARCH_LIBS([lrint], [m])

View File

@ -31,9 +31,9 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
// For file copy // For file copy (fcopyfile currently Mac OSX only)
#include <fcntl.h> #include <fcntl.h>
#if defined(__APPLE__) #if defined(HAVE_FCOPYFILE)
#include <copyfile.h> #include <copyfile.h>
#endif #endif
@ -810,9 +810,9 @@ static int
fast_copy(int fd_dst, int fd_src) fast_copy(int fd_dst, int fd_src)
{ {
// Here we use kernel-space copying for performance reasons // Here we use kernel-space copying for performance reasons
#if defined(__APPLE__) #if defined(HAVE_FCOPYFILE)
return fcopyfile(fd_src, fd_dst, 0, COPYFILE_ALL); return fcopyfile(fd_src, fd_dst, 0, COPYFILE_ALL);
#else #elif defined(HAVE_COPY_FILE_RANGE)
struct stat fileinfo = { 0 }; struct stat fileinfo = { 0 };
ssize_t bytes_copied; ssize_t bytes_copied;
@ -821,6 +821,23 @@ fast_copy(int fd_dst, int fd_src)
if (bytes_copied < 0 || bytes_copied != fileinfo.st_size) if (bytes_copied < 0 || bytes_copied != fileinfo.st_size)
return -1; return -1;
return 0;
#else
unsigned char buf[4096];
ssize_t nr;
while (1)
{
nr = read(fd_src, buf, sizeof(buf));
if (nr == -1)
return -1;
else if (nr == 0)
return 0;
if (write(fd_dst, buf, nr) != nr)
return -1;
}
return 0; return 0;
#endif #endif
} }