Commit d03fd331 by Edward Thomson

clar: copy files with sendfile on linux

parent 8df4f519
/* fcopyfile on macOS is slower than a simple read/write loop? */ /*
* By default, use a read/write loop to copy files on POSIX systems.
* On Linux, use sendfile by default as it's slightly faster. On
* macOS, we avoid fcopyfile by default because it's slightly slower.
*/
#undef USE_FCOPYFILE #undef USE_FCOPYFILE
#define USE_SENDFILE 1
#ifdef _WIN32 #ifdef _WIN32
...@@ -264,6 +269,10 @@ cl_fs_cleanup(void) ...@@ -264,6 +269,10 @@ cl_fs_cleanup(void)
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#if defined(__linux__)
# include <sys/sendfile.h>
#endif
#if defined(__APPLE__) || defined(__FreeBSD__) #if defined(__APPLE__) || defined(__FreeBSD__)
# include <copyfile.h> # include <copyfile.h>
#endif #endif
...@@ -341,12 +350,12 @@ static char *joinpath(const char *dir, const char *base, int base_len) ...@@ -341,12 +350,12 @@ static char *joinpath(const char *dir, const char *base, int base_len)
} }
static void static void
fs_copydir_helper(const char *source, const char *dest, int dmode) fs_copydir_helper(const char *source, const char *dest, int dest_mode)
{ {
DIR *source_dir; DIR *source_dir;
struct dirent *d; struct dirent *d;
mkdir(dest, dmode); mkdir(dest, dest_mode);
cl_assert_(source_dir = opendir(source), "Could not open source dir"); cl_assert_(source_dir = opendir(source), "Could not open source dir");
while ((d = (errno = 0, readdir(source_dir))) != NULL) { while ((d = (errno = 0, readdir(source_dir))) != NULL) {
...@@ -366,20 +375,32 @@ fs_copydir_helper(const char *source, const char *dest, int dmode) ...@@ -366,20 +375,32 @@ fs_copydir_helper(const char *source, const char *dest, int dmode)
} }
static void static void
fs_copyfile_helper(const char *source, const char *dest, int dmode) fs_copyfile_helper(const char *source, size_t source_len, const char *dest, int dest_mode)
{ {
int in, out; int in, out;
cl_must_pass((in = open(source, O_RDONLY))); cl_must_pass((in = open(source, O_RDONLY)));
cl_must_pass((out = open(dest, O_WRONLY|O_CREAT|O_TRUNC, dmode))); cl_must_pass((out = open(dest, O_WRONLY|O_CREAT|O_TRUNC, dest_mode)));
#if USE_FCOPYFILE && (defined(__APPLE__) || defined(__FreeBSD__)) #if USE_FCOPYFILE && (defined(__APPLE__) || defined(__FreeBSD__))
((void)(source_len)); /* unused */
cl_must_pass(fcopyfile(in, out, 0, COPYFILE_DATA)); cl_must_pass(fcopyfile(in, out, 0, COPYFILE_DATA));
#elif USE_SENDFILE && defined(__linux__)
{
ssize_t ret = 0;
while (source_len && (ret = sendfile(out, in, NULL, source_len)) > 0) {
source_len -= (size_t)ret;
}
cl_assert(ret >= 0);
}
#else #else
{ {
char buf[131072]; char buf[131072];
ssize_t ret; ssize_t ret;
((void)(source_len)); /* unused */
while ((ret = read(in, buf, sizeof(buf))) > 0) { while ((ret = read(in, buf, sizeof(buf))) > 0) {
size_t len = (size_t)ret; size_t len = (size_t)ret;
...@@ -427,7 +448,7 @@ fs_copy(const char *source, const char *_dest) ...@@ -427,7 +448,7 @@ fs_copy(const char *source, const char *_dest)
if (S_ISDIR(source_st.st_mode)) { if (S_ISDIR(source_st.st_mode)) {
fs_copydir_helper(source, dest, source_st.st_mode); fs_copydir_helper(source, dest, source_st.st_mode);
} else { } else {
fs_copyfile_helper(source, dest, source_st.st_mode); fs_copyfile_helper(source, source_st.st_size, dest, source_st.st_mode);
} }
free(dbuf); free(dbuf);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment