Recent changes to pread/pwrite in the 0.9.33 branch to use the proper linux kernel syscalls failed to consider architectures that align 64-bit values in register pairs. These targets are already marked because their truncate64 syscall required a different number of args as well.
Use the existing __UCLIBC_TRUNCATE64_HAS_4_ARGS__ definition to also determine whether we should use 5 or 6 args for pread/pwrite. --- libc/sysdeps/linux/common/pread_write.c | 51 +++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/libc/sysdeps/linux/common/pread_write.c b/libc/sysdeps/linux/common/pread_write.c index b13de66..b8d527b 100644 --- a/libc/sysdeps/linux/common/pread_write.c +++ b/libc/sysdeps/linux/common/pread_write.c @@ -43,6 +43,19 @@ extern __typeof(pwrite64) __libc_pwrite64; #include <bits/kernel_types.h> # define __NR___syscall_pread __NR_pread64 +# ifdef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ +static __inline__ _syscall6(ssize_t, __syscall_pread, int, fd, void *, buf, + size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset) +{ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 31, offset)); + LIBC_CANCEL_RESET (oldtype); + return result; + +} +# else static __inline__ _syscall5(ssize_t, __syscall_pread, int, fd, void *, buf, size_t, count, off_t, offset_hi, off_t, offset_lo) @@ -54,9 +67,21 @@ ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset) return result; } +# endif weak_alias(__libc_pread,pread) # ifdef __UCLIBC_HAS_LFS__ +# ifdef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ +ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) +{ + uint32_t low = offset & 0xffffffff; + uint32_t high = offset >> 32; + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR(high, low)); + LIBC_CANCEL_RESET (oldtype); + return result; +} +# else ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) { uint32_t low = offset & 0xffffffff; @@ -66,6 +91,7 @@ ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) LIBC_CANCEL_RESET (oldtype); return result; } +# endif weak_alias(__libc_pread64,pread64) # endif /* __UCLIBC_HAS_LFS__ */ @@ -75,6 +101,18 @@ weak_alias(__libc_pread64,pread64) #endif # define __NR___syscall_pwrite __NR_pwrite +# ifdef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ +static __inline__ _syscall6(ssize_t, __syscall_pwrite, int, fd, const void *, buf, + size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 31, offset)); + LIBC_CANCEL_RESET (oldtype); + return result; +} +# else static __inline__ _syscall5(ssize_t, __syscall_pwrite, int, fd, const void *, buf, size_t, count, off_t, offset_hi, off_t, offset_lo) @@ -85,9 +123,21 @@ ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) LIBC_CANCEL_RESET (oldtype); return result; } +# endif weak_alias(__libc_pwrite,pwrite) # ifdef __UCLIBC_HAS_LFS__ +# ifdef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ +ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) +{ + uint32_t low = offset & 0xffffffff; + uint32_t high = offset >> 32; + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR(high, low)); + LIBC_CANCEL_RESET (oldtype); + return result; +} +# else ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) { uint32_t low = offset & 0xffffffff; @@ -97,5 +147,6 @@ ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) LIBC_CANCEL_RESET (oldtype); return result; } +# endif weak_alias(__libc_pwrite64,pwrite64) # endif /* __UCLIBC_HAS_LFS__ */ -- 1.7.9.5 _______________________________________________ uClibc mailing list uClibc@uclibc.org http://lists.busybox.net/mailman/listinfo/uclibc