1 /*
2  * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
3  *
4  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
5  */
6 /*
7  * Based in part on the files
8  *		./sysdeps/unix/sysv/linux/pwrite.c,
9  *		./sysdeps/unix/sysv/linux/pread.c,
10  *		sysdeps/posix/pread.c
11  *		sysdeps/posix/pwrite.c
12  * from GNU libc 2.2.5, but reworked considerably...
13  */
14 
15 #include <sys/syscall.h>
16 #include <unistd.h>
17 #include <endian.h>
18 #include <bits/wordsize.h>
19 #include <cancel.h>
20 
21 #ifdef __NR_pread64
22 # undef __NR_pread
23 # define __NR_pread __NR_pread64
24 #endif
25 #ifdef __NR_pwrite64
26 # undef __NR_pwrite
27 # define __NR_pwrite __NR_pwrite64
28 #endif
29 
30 #ifndef MY_PREAD
31 # ifdef __NR_pread
32 #  define __NR___syscall_pread __NR_pread
33 #  if defined(__UCLIBC_SYSCALL_ALIGN_64BIT__)
_syscall6(ssize_t,__syscall_pread,int,fd,void *,buf,size_t,count,int,dummy,off_t,offset_hi,off_t,offset_lo)34 static _syscall6(ssize_t, __syscall_pread, int, fd, void *, buf,
35 		 size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo)
36 #   define MY_PREAD(fd, buf, count, offset) __syscall_pread(fd, buf, count, 0, OFF_HI_LO(offset))
37 #   define MY_PREAD64(fd, buf, count, offset) __syscall_pread(fd, buf, count, 0, OFF64_HI_LO(offset))
38 #  elif __WORDSIZE == 32
39 static _syscall5(ssize_t, __syscall_pread, int, fd, void *, buf,
40 		 size_t, count, off_t, offset_hi, off_t, offset_lo)
41 #   define MY_PREAD(fd, buf, count, offset) __syscall_pread(fd, buf, count, OFF_HI_LO(offset))
42 #   define MY_PREAD64(fd, buf, count, offset) __syscall_pread(fd, buf, count, OFF64_HI_LO(offset))
43 #  else
44 static _syscall4(ssize_t, __syscall_pread, int, fd, void *, buf,
45 		 size_t, count, off_t, offset)
46 #   define MY_PREAD(fd, buf, count, offset) __syscall_pread(fd, buf, count, offset)
47 #   define MY_PREAD64(fd, buf, count, offset) __syscall_pread(fd, buf, count, offset)
48 #  endif
49 # endif
50 #endif
51 
52 #ifndef MY_PWRITE
53 # ifdef __NR_pwrite
54 #  define __NR___syscall_pwrite __NR_pwrite
55 #  if defined(__UCLIBC_SYSCALL_ALIGN_64BIT__)
56 static _syscall6(ssize_t, __syscall_pwrite, int, fd, const void *, buf,
57 		 size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo)
58 #   define MY_PWRITE(fd, buf, count, offset) __syscall_pwrite(fd, buf, count, 0, OFF_HI_LO(offset))
59 #   define MY_PWRITE64(fd, buf, count, offset) __syscall_pwrite(fd, buf, count, 0, OFF64_HI_LO(offset))
60 #  elif __WORDSIZE == 32
61 static _syscall5(ssize_t, __syscall_pwrite, int, fd, const void *, buf,
62 		 size_t, count, off_t, offset_hi, off_t, offset_lo)
63 #   define MY_PWRITE(fd, buf, count, offset) __syscall_pwrite(fd, buf, count, OFF_HI_LO(offset))
64 #   define MY_PWRITE64(fd, buf, count, offset) __syscall_pwrite(fd, buf, count, OFF64_HI_LO(offset))
65 #  else
66 static _syscall4(ssize_t, __syscall_pwrite, int, fd, const void *, buf,
67 		 size_t, count, off_t, offset)
68 #   define MY_PWRITE(fd, buf, count, offset) __syscall_pwrite(fd, buf, count, offset)
69 #   define MY_PWRITE64(fd, buf, count, offset) __syscall_pwrite(fd, buf, count, offset)
70 #  endif
71 # endif
72 #endif
73 
74 static ssize_t __NC(pread)(int fd, void *buf, size_t count, off_t offset)
75 {
76 	return MY_PREAD(fd, buf, count, offset);
77 }
78 CANCELLABLE_SYSCALL(ssize_t, pread, (int fd, void *buf, size_t count, off_t offset),
79 		    (fd, buf, count, offset))
80 
__NC(pwrite)81 static ssize_t __NC(pwrite)(int fd, const void *buf, size_t count, off_t offset)
82 {
83 	return MY_PWRITE(fd, buf, count, offset);
84 }
85 CANCELLABLE_SYSCALL(ssize_t, pwrite, (int fd, const void *buf, size_t count, off_t offset),
86 		    (fd, buf, count, offset))
87 
88 #if __WORDSIZE == 32
__NC(pread64)89 static ssize_t __NC(pread64)(int fd, void *buf, size_t count, off64_t offset)
90 {
91 	return MY_PREAD64(fd, buf, count, offset);
92 }
93 CANCELLABLE_SYSCALL(ssize_t, pread64, (int fd, void *buf, size_t count, off64_t offset),
94 		    (fd, buf, count, offset))
95 
__NC(pwrite64)96 static ssize_t __NC(pwrite64)(int fd, const void *buf, size_t count, off64_t offset)
97 {
98 	return MY_PWRITE64(fd, buf, count, offset);
99 }
100 CANCELLABLE_SYSCALL(ssize_t, pwrite64, (int fd, const void *buf, size_t count, off64_t offset),
101 		    (fd, buf, count, offset))
102 #else
103 # ifdef __UCLIBC_HAS_LINUXTHREADS__
104 weak_alias(pread,pread64)
105 weak_alias(pwrite,pwrite64)
106 lt_strong_alias(pread64)
107 lt_strong_alias(pwrite64)
108 # else
109 strong_alias_untyped(pread,pread64)
110 strong_alias_untyped(pwrite,pwrite64)
111 # endif
112 #endif
113