diff --git a/11-sendfile/sendfile.c b/11-sendfile/sendfile.c
index cf156c9..782d322 100644
--- a/11-sendfile/sendfile.c
+++ b/11-sendfile/sendfile.c
@@ -22,12 +22,56 @@
ssize_t copy_write(int fd_in, int fd_out, int *syscalls) {
ssize_t ret = 0;
*syscalls = 0;
+ // For the read/write copy method, we require a buffer. To not
+ // hinder performance, we use a static function variable to
+ // allocate the buffer once (it is never freed.
+ static size_t bufsize = 128 * 1024; // GNU cp uses 128k Buffers
+ static char *buffer = NULL;
+ if (!buffer) {
+ buffer = malloc(bufsize);
+ if(!buffer) die("malloc");
+ }
+
+ // The actual copy loop
+ do {
+ // Read up to bufsize bytes.
+ int len = read(fd_in, buffer, bufsize);
+ if (len < 0) die("read");
+ (*syscalls) ++; // read is a system call
+ if (len == 0) break; // end-of file is reached
+
+ // As write could be short, we loop until all bytes are
+ // written to the output file descriptor.
+ int written = 0;
+ while (written < len) {
+ int wlen = write(fd_out, buffer+written, len-written);
+ if (wlen < 0) die("write");
+ (*syscalls) ++;
+ written += wlen;
+ }
+ // Account for the copied bytes.
+ ret += len;
+ } while(1);
+
return ret;
}
ssize_t copy_sendfile(int fd_in, int fd_out, int *syscalls) {
ssize_t ret = 0;
*syscalls = 0;
+
+ // For sendfile, we do not require a buffer, but we can directly
+ // call sendfile on both descriptors. Please note how insane the
+ // order of the arguments (dest, source) is!
+ do {
+ int len = sendfile(fd_out, fd_in, NULL, INT_MAX);
+ if (len < 0) die("sendfile");
+ (*syscalls)++;
+ if (len == 0) break; // end of file
+
+ // Account for the copied bytes
+ ret += len;
+ } while(1);
return ret;
}