OSDN Git Service

powerpc: Add TLS and NPTL support
[uclinux-h8/uClibc.git] / libc / sysdeps / linux / powerpc / pread_write.c
1 /* vi: set sw=4 ts=4:
2  *
3  * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
4  *
5  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
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
19 #ifndef __UCLIBC_HAS_LFS__
20 # define off64_t off_t
21 #endif
22
23 #ifdef __NR_pread
24 extern __typeof(pread) __libc_pread;
25 # define __NR___syscall_pread __NR_pread
26 static __inline__ _syscall6(ssize_t, __syscall_pread, int, fd,
27                 void *, buf, size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo)
28
29 ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset)
30 {
31         return(__syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 31, offset)));
32 }
33 weak_alias(__libc_pread,pread)
34
35 # ifdef __UCLIBC_HAS_LFS__
36 extern __typeof(pread64) __libc_pread64;
37 ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset)
38 {
39         return(__syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 32, offset)));
40 }
41 weak_alias(__libc_pread64,pread64)
42 # endif /* __UCLIBC_HAS_LFS__  */
43 #endif /* __NR_pread */
44
45
46 #ifdef __NR_pwrite
47 extern __typeof(pwrite) __libc_pwrite;
48 # define __NR___syscall_pwrite __NR_pwrite
49 static __inline__ _syscall6(ssize_t, __syscall_pwrite, int, fd,
50                 const void *, buf, size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo)
51
52 ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset)
53 {
54         return(__syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 31, offset)));
55 }
56 weak_alias(__libc_pwrite,pwrite)
57
58 # ifdef __UCLIBC_HAS_LFS__
59 extern __typeof(pwrite64) __libc_pwrite64;
60 ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset)
61 {
62         return(__syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 32, offset)));
63 }
64 weak_alias(__libc_pwrite64,pwrite64)
65 # endif /* __UCLIBC_HAS_LFS__  */
66 #endif /* __NR_pwrite */
67
68
69
70 #if ! defined __NR_pread || ! defined __NR_pwrite
71
72 static ssize_t __fake_pread_write(int fd, void *buf,
73                 size_t count, off_t offset, int do_pwrite)
74 {
75         int save_errno;
76         ssize_t result;
77         off_t old_offset;
78
79         /* Since we must not change the file pointer preserve the
80          * value so that we can restore it later.  */
81         if ((old_offset=lseek(fd, 0, SEEK_CUR)) == (off_t) -1)
82                 return -1;
83
84         /* Set to wanted position.  */
85         if (lseek (fd, offset, SEEK_SET) == (off_t) -1)
86                 return -1;
87
88         if (do_pwrite == 1) {
89                 /* Write the data.  */
90                 result = write(fd, buf, count);
91         } else {
92                 /* Read the data.  */
93                 result = read(fd, buf, count);
94         }
95
96         /* Now we have to restore the position.  If this fails we
97          * have to return this as an error.  */
98         save_errno = errno;
99         if (lseek(fd, old_offset, SEEK_SET) == (off_t) -1)
100         {
101                 if (result == -1)
102                         __set_errno(save_errno);
103                 return -1;
104         }
105         __set_errno(save_errno);
106         return(result);
107 }
108
109 # ifdef __UCLIBC_HAS_LFS__
110
111 static ssize_t __fake_pread_write64(int fd, void *buf,
112                 size_t count, off64_t offset, int do_pwrite)
113 {
114         int save_errno;
115         ssize_t result;
116         off64_t old_offset;
117
118         /* Since we must not change the file pointer preserve the
119          * value so that we can restore it later.  */
120         if ((old_offset=lseek64(fd, 0, SEEK_CUR)) == (off64_t) -1)
121                 return -1;
122
123         /* Set to wanted position.  */
124         if (lseek64(fd, offset, SEEK_SET) == (off64_t) -1)
125                 return -1;
126
127         if (do_pwrite == 1) {
128                 /* Write the data.  */
129                 result = write(fd, buf, count);
130         } else {
131                 /* Read the data.  */
132                 result = read(fd, buf, count);
133         }
134
135         /* Now we have to restore the position. */
136         save_errno = errno;
137         if (lseek64 (fd, old_offset, SEEK_SET) == (off64_t) -1) {
138                 if (result == -1)
139                         __set_errno (save_errno);
140                 return -1;
141         }
142         __set_errno (save_errno);
143         return result;
144 }
145 # endif /* __UCLIBC_HAS_LFS__  */
146 #endif /*  ! defined __NR_pread || ! defined __NR_pwrite */
147
148 #ifndef __NR_pread
149 ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset);
150 ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset)
151 {
152         return(__fake_pread_write(fd, buf, count, offset, 0));
153 }
154 weak_alias(__libc_pread,pread)
155
156 # ifdef __UCLIBC_HAS_LFS__
157 ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset);
158 ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset)
159 {
160         return(__fake_pread_write64(fd, buf, count, offset, 0));
161 }
162 weak_alias(__libc_pread64,pread64)
163 # endif /* __UCLIBC_HAS_LFS__  */
164 #endif /* ! __NR_pread */
165
166
167 #ifndef __NR_pwrite
168 ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset);
169 ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset)
170 {
171         return(__fake_pread_write(fd, (void*)buf, count, offset, 1));
172 }
173 weak_alias(__libc_pwrite,pwrite)
174
175 # ifdef __UCLIBC_HAS_LFS__
176 ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset);
177 ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset)
178 {
179         return(__fake_pread_write64(fd, (void*)buf, count, offset, 1));
180 }
181 weak_alias(__libc_pwrite64,pwrite64)
182 # endif /* __UCLIBC_HAS_LFS__  */
183 #endif /* ! __NR_pwrite */