summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-08-28 00:10:35 +0200
committerLennart Poettering <lennart@poettering.net>2015-08-28 02:05:42 +0200
commit81d20007f966e36cc8c9161b7117f3f1affdba02 (patch)
treecf6e5430e667e67643a7041e45ea359b3d9b295f
parentd56cc298808b2dbfa28ae893d6f47f34df3196b1 (diff)
copy: add splice() based fallback
Apparently, sendfile() does not work between fifos and ttys, but splice() does, hence let's optionally fall back to that. This is useful to implement the fallback pager this way.
-rw-r--r--src/basic/copy.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/src/basic/copy.c b/src/basic/copy.c
index 33427c6a73..cc5faa80a1 100644
--- a/src/basic/copy.c
+++ b/src/basic/copy.c
@@ -30,7 +30,7 @@
#define COPY_BUFFER_SIZE (16*1024)
int copy_bytes(int fdf, int fdt, off_t max_bytes, bool try_reflink) {
- bool try_sendfile = true;
+ bool try_sendfile = true, try_splice = true;
int r;
assert(fdf >= 0);
@@ -69,7 +69,23 @@ int copy_bytes(int fdf, int fdt, off_t max_bytes, bool try_reflink) {
} else if (n == 0) /* EOF */
break;
else if (n > 0)
- /* Succcess! */
+ /* Success! */
+ goto next;
+ }
+
+ /* The try splice, unless we already tried */
+ if (try_splice) {
+ n = splice(fdf, NULL, fdt, NULL, m, 0);
+ if (n < 0) {
+ if (errno != EINVAL && errno != ENOSYS)
+ return -errno;
+
+ try_splice = false;
+ /* use fallback below */
+ } else if (n == 0) /* EOF */
+ break;
+ else if (n > 0)
+ /* Success! */
goto next;
}