Whamcloud - gitweb
fcd463a9cb3b41bccf18717015a5dcfcac46e20a
[fs/lustre-release.git] / libsysio / src / stdlib.c
1 /*
2  * This library is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU Lesser General Public
4  * License as published by the Free Software Foundation; either
5  * version 2.1 of the License, or (at your option) any later version.
6  * 
7  * This library is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10  * Lesser General Public License for more details.
11  * 
12  * You should have received a copy of the GNU Lesser General Public
13  * License along with this library; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15  *
16  */
17
18 /*
19  * stdlib.c
20  *
21  * The only purpose of this file is help liblustre adaptive to more
22  * applications, and specifically for running on Linux. The ideal
23  * final solution would be remove this completely and only rely on
24  * system call interception. Unfortunately we failed to find that
25  * way at the moment.
26  *
27  * Initially we try the simplest implementation here, just get a confidence
28  * it could work.
29  *
30  */
31 #if !(defined(BSD) || defined(REDSTORM))
32
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <dirent.h>
37
38 #include <sysio.h>
39
40 #include "sysio-symbols.h"
41
42 #if !defined(__USE_LARGEFILE64)
43 #error "__LARGEFILE64_SOURCE must be defined"
44 #endif
45
46
47 /***********************************************************
48  * dir series functions                                    *
49  ***********************************************************/
50
51 #undef  BUFSIZE
52 #define BUFSIZE 4096
53
54 struct __dirstream {
55         int               fd;
56         loff_t            base;
57         loff_t            filepos;       /* current pos in dir file stream */
58         struct dirent    *curent;        /* current dirent pointer */
59         struct dirent64  *curent64;      /* current dirent64 pointer */
60         struct dirent    *retent;        /* ent returned to caller */
61         struct dirent64  *retent64;      /* ent64 returned to caller */
62         unsigned int      effective;     /* effective data size in buffer */
63         char              buf[BUFSIZE];
64 };
65
66 DIR* opendir(const char *name)
67 {
68         DIR *dir;
69
70         dir = (DIR *) malloc(sizeof(*dir));
71         if (!dir) {
72                 errno = ENOMEM;
73                 return NULL;
74         }
75
76 #if __USE_LARGEFILE64
77         dir->fd = open64(name, O_RDONLY);
78 #else
79         dir->fd = open(name, O_RDONLY);
80 #endif
81         if (dir->fd < 0)
82                 goto err_out;
83
84         dir->base = 0;
85         dir->filepos = 0;
86         dir->curent = (struct dirent *) dir->buf;
87         dir->curent64 = (struct dirent64 *) dir->buf;
88         dir->retent = NULL;
89         dir->retent64 = NULL;
90         dir->effective = 0;
91
92         return dir;
93 err_out:
94         free(dir);
95         return NULL;
96 }
97
98 sysio_sym_weak_alias(opendir, __opendir);
99
100 struct dirent64 *readdir64(DIR *dir)
101 {
102         int rc, reclen;
103
104         /* need to read new data? */
105         if ((char*)dir->curent64 - dir->buf >= dir->effective) {
106                 rc = getdirentries64(dir->fd, dir->buf, BUFSIZE, &dir->base);
107                 /* error or end-of-file */
108                 if (rc <= 0)
109                         return NULL;
110
111                 dir->curent64 = (struct dirent64 *) dir->buf;
112                 dir->effective = rc;
113         }
114
115         dir->retent64 = dir->curent64;
116         dir->curent64 = (struct dirent64*) ((char *)(dir->curent64) +
117                                 dir->curent64->d_reclen);
118 #ifdef _DIRENT_HAVE_D_OFF
119         dir->filepos = dir->curent64->d_off;
120 #else
121         dir->filepos += dir->curent64->d_reclen;
122 #endif
123         return dir->retent64;
124 }
125
126 sysio_sym_weak_alias(readdir64, __readdir64);
127
128 /* XXX probably the following assumption is not true */
129 #if __WORDSIZE == 64
130 #define NATURAL_READDIR64
131 #else
132 #undef  NATURAL_READDIR64
133 #endif
134
135 #ifndef NATURAL_READDIR64
136
137 struct dirent *readdir(DIR *dir)
138 {
139         int rc, reclen;
140
141         /* need to read new data? */
142         if ((char*)dir->curent - dir->buf >= dir->effective) {
143                 rc = getdirentries(dir->fd, dir->buf, BUFSIZE, (off_t*) &dir->base);
144                 /* error or end-of-file */
145                 if (rc <= 0)
146                         return NULL;
147
148                 dir->curent = (struct dirent *) dir->buf;
149                 dir->effective = rc;
150         }
151
152         dir->retent = dir->curent;
153         dir->curent = (struct dirent*) ((char *)(dir->curent) +
154                                 dir->curent->d_reclen);
155 #ifdef _DIRENT_HAVE_D_OFF
156         dir->filepos = dir->curent->d_off;
157 #else
158         dir->filepos += dir->curent->d_reclen;
159 #endif
160         return dir->retent;
161 }
162 sysio_sym_weak_alias(readdir, __readdir);
163
164 #else /* NATURAL_READDIR64 */
165
166 struct dirent *readdir(DIR *dir) {
167         return (struct dirent *) readdir64(dir);
168 }
169 sysio_sym_weak_alias(readdir, __readdir);
170
171 #endif /* NATURAL_READDIR64 */
172
173 int closedir(DIR *dir)
174 {
175         int rc;
176
177         rc = close(dir->fd);
178
179         free(dir);
180         return rc;
181 }
182
183 sysio_sym_weak_alias(closedir, __closedir);
184
185 int dirfd(DIR *dir)
186 {
187         return dir->fd;
188 }
189
190 off_t telldir(DIR *dir)
191 {
192         return (dir->filepos);
193 }
194
195 void seekdir(DIR *dir, off_t offset)
196 {
197         dir->filepos = offset;
198
199         dir->base = offset;
200         dir->curent64 = (struct dirent64 *) dir->buf;
201         dir->retent64 = NULL;
202         dir->effective = 0;
203         dir->curent = (struct dirent *) dir->buf;
204         dir->retent = NULL;
205 }
206
207 void rewinddir(DIR *dir)
208 {
209         dir->base = 0;
210         dir->filepos = 0;
211         dir->curent64 = (struct dirent64 *) dir->buf;
212         dir->retent64 = NULL;
213         dir->curent = (struct dirent *) dir->buf;
214         dir->retent = NULL;
215         dir->effective = 0;
216 }
217
218 #if 0
219 int scandir(const char *dir, struct dirent ***namelist,
220             int(*select)(const struct dirent *),
221             int(*compar)(const void *, const void *))
222 {
223         errno = ENOSYS;
224         return -1;
225 }
226
227 int scandir64(const char *dir, struct dirent64 ***namelist,
228               int(*select)(const struct dirent64 *),
229               int(*compar)(const void *, const void *))
230 {
231         errno = ENOSYS;
232         return -1;
233 }
234 #endif
235
236 /***********************************************************
237  * FIXME workaround for linux only                         *
238  ***********************************************************/
239
240 #define LINUX
241 #if defined(LINUX)
242 ssize_t getxattr(char *path, char *name, void *value, size_t size)
243 {
244         errno = ENOSYS;
245         return -1;
246 }
247
248 ssize_t lgetxattr(char *path, char *name, void *value, size_t size)
249 {
250         errno = ENOSYS;
251         return -1;
252 }
253
254 ssize_t fgetxattr(int fd, char *name, void *value, size_t size)
255 {
256         errno = ENOSYS;
257         return -1;
258 }
259
260 long setxattr(char *path, char *name, void *value, size_t size, int flags)
261 {
262         errno = ENOSYS;
263         return -1;
264 }
265
266 long lsetxattr(char *path, char *name, void *value, size_t size, int flags)
267 {
268         errno = ENOSYS;
269         return -1;
270 }
271
272 long fsetxattr(int fd, char *name, void *value, size_t size, int flags)
273 {
274         errno = ENOSYS;
275         return -1;
276 }
277
278 long listxattr(char *path, char *list, size_t size)
279 {
280         errno = ENOSYS;
281         return -1;
282 }
283
284 long llistxattr(char *path, char *list, size_t size)
285 {
286         errno = ENOSYS;
287         return -1;
288 }
289
290 long flistxattr(int fd, char *list, size_t size)
291 {
292         errno = ENOSYS;
293         return -1;
294 }
295
296 long removexattr(char *path, char *name)
297 {
298         errno = ENOSYS;
299         return -1;
300 }
301
302 long lremovexattr(char *path, char *name)
303 {
304         errno = ENOSYS;
305         return -1;
306 }
307
308 long fremovexattr(int fd, char *name)
309 {
310         errno = ENOSYS;
311         return -1;
312 }
313 #endif
314
315 #endif