summaryrefslogtreecommitdiffstats
path: root/usr/klibc/lseek.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/klibc/lseek.c')
-rw-r--r--usr/klibc/lseek.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/usr/klibc/lseek.c b/usr/klibc/lseek.c
new file mode 100644
index 0000000..f262d19
--- /dev/null
+++ b/usr/klibc/lseek.c
@@ -0,0 +1,31 @@
+/*
+ * lseek.c
+ *
+ * On 32-bit platforms, we need to use the _llseek() system call
+ * rather than lseek(), to be able to handle large disks. _llseek()
+ * isn't just a normal syscall which takes a 64-bit argument; it needs
+ * to return a 64-bit value and so takes an extra pointer.
+ */
+
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <bitsize.h>
+
+#if _BITSIZE == 32
+
+extern int __llseek(int fd, unsigned long hi, unsigned long lo, off_t * res,
+ int whence);
+
+off_t lseek(int fd, off_t offset, int whence)
+{
+ unsigned long long ullo = offset;
+ off_t result;
+ int rv;
+
+ rv = __llseek(fd, (unsigned long)(ullo >> 32), (unsigned long)ullo,
+ &result, whence);
+
+ return rv ? (off_t)-1 : result;
+}
+
+#endif