aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/mach/hurd/sendfile64.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/mach/hurd/sendfile64.c')
-rw-r--r--sysdeps/mach/hurd/sendfile64.c41
1 files changed, 29 insertions, 12 deletions
diff --git a/sysdeps/mach/hurd/sendfile64.c b/sysdeps/mach/hurd/sendfile64.c
index 40ce271efb..1f63d2a2f5 100644
--- a/sysdeps/mach/hurd/sendfile64.c
+++ b/sysdeps/mach/hurd/sendfile64.c
@@ -18,26 +18,43 @@
02111-1307 USA. */
#include <sys/sendfile.h>
-#include <errno.h>
-#include <stddef.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+#include <sys/mman.h>
/* Send COUNT bytes from file associated with IN_FD starting at OFFSET to
descriptor OUT_FD. */
ssize_t
sendfile64 (int out_fd, int in_fd, off64_t *offset, size_t count)
{
- if (offset == NULL)
- return sendfile (out_fd, in_fd, NULL, count);
- else
+ /* We just do a vanilla io_read followed by a vanilla io_write here.
+ In theory the IN_FD filesystem can return us out-of-line data that
+ we then send out-of-line to the OUT_FD filesystem and no copying
+ takes place until those pages need to be flushed or packaged by
+ that filesystem (e.g. packetized by a network socket). However,
+ we momentarily consume COUNT bytes of our local address space,
+ which might blow if it's huge or address space is real tight. */
+
+ char *data = 0;
+ size_t datalen = 0;
+ error_t err = HURD_DPORT_USE (in_fd,
+ __io_read (port, &data, &datalen,
+ offset ? *offset : (off_t) -1,
+ count));
+ if (err == 0)
{
- off_t ofs = *offset;
- if (ofs != *offset)
+ size_t nwrote;
+ if (datalen == 0)
+ return 0;
+ err = HURD_DPORT_USE (out_fd, __io_write (port, data, datalen,
+ (off_t) -1, &nwrote));
+ munmap (data, datalen);
+ if (err == 0)
{
- __set_errno (EOVERFLOW);
- return -1;
+ if (offset)
+ *offset += datalen;
+ return nwrote;
}
- ssize_t ret = sendfile (out_fd, in_fd, &ofs, count);
- *offset = ofs;
- return ret;
}
+ return __hurd_fail (err);
}