Skip to content

Commit d03fd33

Browse files
committed
clar: copy files with sendfile on linux
1 parent 8df4f51 commit d03fd33

File tree

1 file changed

+27
-6
lines changed

1 file changed

+27
-6
lines changed

tests/clar/fs.h

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1-
/* fcopyfile on macOS is slower than a simple read/write loop? */
1+
/*
2+
* By default, use a read/write loop to copy files on POSIX systems.
3+
* On Linux, use sendfile by default as it's slightly faster. On
4+
* macOS, we avoid fcopyfile by default because it's slightly slower.
5+
*/
26
#undef USE_FCOPYFILE
7+
#define USE_SENDFILE 1
38

49
#ifdef _WIN32
510

@@ -264,6 +269,10 @@ cl_fs_cleanup(void)
264269
#include <sys/types.h>
265270
#include <sys/stat.h>
266271

272+
#if defined(__linux__)
273+
# include <sys/sendfile.h>
274+
#endif
275+
267276
#if defined(__APPLE__) || defined(__FreeBSD__)
268277
# include <copyfile.h>
269278
#endif
@@ -341,12 +350,12 @@ static char *joinpath(const char *dir, const char *base, int base_len)
341350
}
342351

343352
static void
344-
fs_copydir_helper(const char *source, const char *dest, int dmode)
353+
fs_copydir_helper(const char *source, const char *dest, int dest_mode)
345354
{
346355
DIR *source_dir;
347356
struct dirent *d;
348357

349-
mkdir(dest, dmode);
358+
mkdir(dest, dest_mode);
350359

351360
cl_assert_(source_dir = opendir(source), "Could not open source dir");
352361
while ((d = (errno = 0, readdir(source_dir))) != NULL) {
@@ -366,20 +375,32 @@ fs_copydir_helper(const char *source, const char *dest, int dmode)
366375
}
367376

368377
static void
369-
fs_copyfile_helper(const char *source, const char *dest, int dmode)
378+
fs_copyfile_helper(const char *source, size_t source_len, const char *dest, int dest_mode)
370379
{
371380
int in, out;
372381

373382
cl_must_pass((in = open(source, O_RDONLY)));
374-
cl_must_pass((out = open(dest, O_WRONLY|O_CREAT|O_TRUNC, dmode)));
383+
cl_must_pass((out = open(dest, O_WRONLY|O_CREAT|O_TRUNC, dest_mode)));
375384

376385
#if USE_FCOPYFILE && (defined(__APPLE__) || defined(__FreeBSD__))
386+
((void)(source_len)); /* unused */
377387
cl_must_pass(fcopyfile(in, out, 0, COPYFILE_DATA));
388+
#elif USE_SENDFILE && defined(__linux__)
389+
{
390+
ssize_t ret = 0;
391+
392+
while (source_len && (ret = sendfile(out, in, NULL, source_len)) > 0) {
393+
source_len -= (size_t)ret;
394+
}
395+
cl_assert(ret >= 0);
396+
}
378397
#else
379398
{
380399
char buf[131072];
381400
ssize_t ret;
382401

402+
((void)(source_len)); /* unused */
403+
383404
while ((ret = read(in, buf, sizeof(buf))) > 0) {
384405
size_t len = (size_t)ret;
385406

@@ -427,7 +448,7 @@ fs_copy(const char *source, const char *_dest)
427448
if (S_ISDIR(source_st.st_mode)) {
428449
fs_copydir_helper(source, dest, source_st.st_mode);
429450
} else {
430-
fs_copyfile_helper(source, dest, source_st.st_mode);
451+
fs_copyfile_helper(source, source_st.st_size, dest, source_st.st_mode);
431452
}
432453

433454
free(dbuf);

0 commit comments

Comments
 (0)