summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkos Chandras <markos.chandras@imgtec.com>2012-10-11 11:20:42 +0100
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2013-02-20 13:45:12 +0100
commita83ea57a508362f8f66ecd89131302fba1223637 (patch)
tree18dbdf27ad89846869afc61dc33edfa085c85c57
parentf7bead5adac96d9cb72aa2fb3c11ca5ab8f5f6b9 (diff)
sendfile: Use sendfile64 if arch does not have the sendfile syscall
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com> Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
-rw-r--r--include/sys/sendfile.h1
-rw-r--r--libc/sysdeps/linux/common/sendfile.c45
-rw-r--r--libc/sysdeps/linux/common/sendfile64.c1
-rw-r--r--libc/sysdeps/linux/common/stubs.c3
4 files changed, 48 insertions, 2 deletions
diff --git a/include/sys/sendfile.h b/include/sys/sendfile.h
index dd6c0348d..dae074c05 100644
--- a/include/sys/sendfile.h
+++ b/include/sys/sendfile.h
@@ -44,6 +44,7 @@ extern ssize_t __REDIRECT_NTH (sendfile,
#ifdef __USE_LARGEFILE64
extern ssize_t sendfile64 (int __out_fd, int __in_fd, __off64_t *__offset,
size_t __count) __THROW;
+libc_hidden_proto(sendfile64)
#endif
__END_DECLS
diff --git a/libc/sysdeps/linux/common/sendfile.c b/libc/sysdeps/linux/common/sendfile.c
index 64c200eb2..2bd717929 100644
--- a/libc/sysdeps/linux/common/sendfile.c
+++ b/libc/sysdeps/linux/common/sendfile.c
@@ -9,12 +9,55 @@
#include <sys/syscall.h>
-#ifdef __NR_sendfile
# include <sys/sendfile.h>
# include <bits/wordsize.h>
+
+#if defined __NR_sendfile
_syscall4(ssize_t, sendfile, int, out_fd, int, in_fd, __off_t *, offset,
size_t, count)
# if defined __UCLIBC_HAS_LFS__ && (!defined __NR_sendfile64 || __WORDSIZE == 64)
strong_alias_untyped(sendfile,sendfile64)
# endif
+
+#elif defined __NR_sendfile64 && !defined __NR_sendfile
+# include <unistd.h>
+# include <stddef.h>
+
+ssize_t sendfile(int out_fd, int in_fd, __off_t *offset, size_t count)
+{
+ __off64_t off64, *off;
+ ssize_t res;
+
+ /*
+ * Check if valid fds and valid pointers were passed
+ * This does not prevent the user from passing
+ * an arbitrary pointer causing a segfault or
+ * other security issues
+ */
+
+ if (in_fd < 0 || out_fd < 0) {
+ __set_errno(EBADF);
+ return -1;
+ }
+
+ if (offset == NULL || (int)offset < 0) {
+ __set_errno(EFAULT);
+ return -1;
+ }
+
+ if (offset) {
+ off = &off64;
+ off64 = *offset;
+ } else {
+ off = NULL;
+ }
+
+ res = INLINE_SYSCALL(sendfile64, 4, out_fd, in_fd, off, count);
+
+ if (res >= 0)
+ *offset = off64;
+
+ return res;
+}
+
#endif
diff --git a/libc/sysdeps/linux/common/sendfile64.c b/libc/sysdeps/linux/common/sendfile64.c
index 705e6fdee..1c01ace7f 100644
--- a/libc/sysdeps/linux/common/sendfile64.c
+++ b/libc/sysdeps/linux/common/sendfile64.c
@@ -17,4 +17,5 @@
#if defined __NR_sendfile64 && __WORDSIZE != 64
# include <sys/sendfile.h>
_syscall4(ssize_t,sendfile64, int, out_fd, int, in_fd, __off64_t *, offset, size_t, count)
+libc_hidden_def(sendfile64)
#endif
diff --git a/libc/sysdeps/linux/common/stubs.c b/libc/sysdeps/linux/common/stubs.c
index 419557c6a..43a1b6938 100644
--- a/libc/sysdeps/linux/common/stubs.c
+++ b/libc/sysdeps/linux/common/stubs.c
@@ -320,7 +320,8 @@ make_stub(sched_setaffinity)
make_stub(send)
#endif
-#if !defined __NR_sendfile && defined __UCLIBC_LINUX_SPECIFIC__
+#if !defined __NR_sendfile && !defined __NR_sendfile64 \
+ && defined __UCLIBC_LINUX_SPECIFIC__
make_stub(sendfile)
#endif