OSDN Git Service

This draws from an old patch by David Blythe for the now-dead
[uclinux-h8/uClibc.git] / libc / sysdeps / linux / powerpc / pread_write.c
1 /* vi: set sw=4 ts=4:
2  *
3  * Copyright (C) 2002 by Erik Andersen <andersen@uclibc.org>
4  * Based in part on the files
5  *              ./sysdeps/unix/sysv/linux/pwrite.c,
6  *              ./sysdeps/unix/sysv/linux/pread.c, 
7  *              sysdeps/posix/pread.c
8  *              sysdeps/posix/pwrite.c
9  * from GNU libc 2.2.5, but reworked considerably...
10  *
11  * This program is free software; you can redistribute it and/or modify it
12  * under the terms of the GNU Library General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or (at your
14  * option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful, but WITHOUT
17  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
19  * for more details.
20  *
21  * You should have received a copy of the GNU Library General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24  */
25
26 #define _GNU_SOURCE
27 #define _LARGEFILE64_SOURCE
28 #include <features.h>
29 #undef __OPTIMIZE__
30 /* We absolutely do _NOT_ want interfaces silently
31  *  *  * renamed under us or very bad things will happen... */
32 #ifdef __USE_FILE_OFFSET64
33 # undef __USE_FILE_OFFSET64
34 #endif
35
36
37 #include <errno.h>
38 #include <sys/types.h>
39 #include <sys/syscall.h>
40 #include <unistd.h>
41
42 #ifdef __NR_pread
43 #define __NR___syscall_pread __NR_pread 
44 static inline _syscall4(ssize_t, __syscall_pread, int, fd, 
45                 void *, buf, size_t, count, off64_t, offset);
46
47 ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset)
48
49         return(__syscall_pread(fd, buf, count, (off64_t)offset));
50 }
51 weak_alias (__libc_pread, pread)
52
53 #if defined __UCLIBC_HAS_LFS__ 
54 ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset)
55
56         return(__syscall_pread(fd, buf, count, offset));
57 }
58 weak_alias (__libc_pread64, pread64)
59 #endif /* __UCLIBC_HAS_LFS__  */
60 #endif /* __NR_pread */
61
62
63 #ifdef __NR_pwrite
64 #define __NR___syscall_pwrite __NR_pwrite 
65 static inline _syscall4(ssize_t, __syscall_pwrite, int, fd, 
66                 const void *, buf, size_t, count, off64_t, offset);
67
68 ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset)
69
70         return(__syscall_pwrite(fd, buf, count, (off64_t)offset));
71 }
72 weak_alias (__libc_pwrite, pwrite)
73
74 #if defined __UCLIBC_HAS_LFS__ 
75 ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset)
76
77         return(__syscall_pwrite(fd, buf, count, offset));
78 }
79 weak_alias (__libc_pwrite64, pwrite64)
80 #endif /* __UCLIBC_HAS_LFS__  */
81 #endif /* __NR_pwrite */
82
83
84
85 #if ! defined __NR_pread || ! defined __NR_pwrite
86 static ssize_t __fake_pread_write(int fd, void *buf, 
87                 size_t count, off_t offset, int do_pwrite)
88 {
89         int save_errno;
90         ssize_t result;
91         off_t old_offset;
92
93         /* Since we must not change the file pointer preserve the 
94          * value so that we can restore it later.  */
95         if ((old_offset=lseek(fd, 0, SEEK_CUR)) == (off_t) -1)
96                 return -1;
97
98         /* Set to wanted position.  */
99         if (lseek (fd, offset, SEEK_SET) == (off_t) -1)
100                 return -1;
101
102         if (do_pwrite==1) {
103                 /* Write the data.  */
104                 result = write(fd, buf, count);
105         } else {
106                 /* Read the data.  */
107                 result = read(fd, buf, count);
108         }
109
110         /* Now we have to restore the position.  If this fails we 
111          * have to return this as an error.  */
112         save_errno = errno;
113         if (lseek(fd, old_offset, SEEK_SET) == (off_t) -1)
114         {
115                 if (result == -1)
116                         __set_errno(save_errno);
117                 return -1;
118         }
119         __set_errno(save_errno);
120         return(result);
121 }
122
123 #if defined __UCLIBC_HAS_LFS__ 
124 static ssize_t __fake_pread_write64(int fd, void *buf, 
125                 size_t count, off64_t offset, int do_pwrite)
126 {
127         int save_errno;
128         ssize_t result;
129         off64_t old_offset;
130
131         /* Since we must not change the file pointer preserve the 
132          * value so that we can restore it later.  */
133         if ((old_offset=lseek64(fd, 0, SEEK_CUR)) == (off64_t) -1)
134                 return -1;
135
136         /* Set to wanted position.  */
137         if (lseek64(fd, offset, SEEK_SET) == (off64_t) -1) 
138                 return -1;                               
139
140         if (do_pwrite==1) {
141                 /* Write the data.  */
142                 result = write(fd, buf, count);
143         } else {
144                 /* Read the data.  */
145                 result = read(fd, buf, count);
146         }
147
148         /* Now we have to restore the position. */
149         save_errno = errno;
150         if (lseek64 (fd, old_offset, SEEK_SET) == (off64_t) -1) {
151                 if (result == -1)
152                         __set_errno (save_errno);
153                 return -1;
154         }
155         __set_errno (save_errno);
156         return result;
157 }
158 #endif /* __UCLIBC_HAS_LFS__  */
159 #endif /*  ! defined __NR_pread || ! defined __NR_pwrite */
160
161 #ifndef __NR_pread
162 ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset)
163 {
164         return(__fake_pread_write(fd, buf, count, offset, 0));
165 }
166 weak_alias (__libc_pread, pread)
167
168 #if defined __UCLIBC_HAS_LFS__ 
169 ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset)
170
171         return(__fake_pread_write64(fd, buf, count, offset, 0));
172 }
173 weak_alias (__libc_pread64, pread64)
174 #endif /* __UCLIBC_HAS_LFS__  */
175 #endif /* ! __NR_pread */
176
177
178 #ifndef __NR_pwrite
179 ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset)
180 {
181         return(__fake_pread_write(fd, buf, count, offset, 1));
182 }
183 weak_alias (__libc_pwrite, pwrite)
184
185 #if defined __UCLIBC_HAS_LFS__ 
186 ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset)
187
188         return(__fake_pread_write64(fd, (void*)buf, count, offset, 1));
189 }
190 weak_alias (__libc_pwrite64, pwrite64)
191 #endif /* __UCLIBC_HAS_LFS__  */
192 #endif /* ! __NR_pwrite */
193