Whamcloud - gitweb
b=20668
[fs/lustre-release.git] / libsysio / src / readdir.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 #ifdef __linux__
19 #include <features.h>
20 #if defined(__GLIBC__) && !defined(REDSTORM) 
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <dirent.h>
27 #include <sysio.h>
28
29 #include "sysio-symbols.h"
30
31 #ifndef _READDIR
32 #define _READDIR SYSIO_INTERFACE_NAME(readdir)
33 #define _SCANDIR SYSIO_INTERFACE_NAME(scandir)
34 #define _GETDIRENTRIES SYSIO_INTERFACE_NAME(getdirentries)
35 #define _DIRENT_T struct dirent
36 #define _OFF_T off_t
37 #endif
38
39 #include "stddir.h"
40
41 _DIRENT_T *
42 _READDIR(DIR *dir)
43 {
44         _DIRENT_T *dp = NULL;
45         _OFF_T dbase;
46
47 #ifndef BSD
48         ssize_t rc;
49 #else
50         int rc;
51 #endif
52         SYSIO_INTERFACE_DISPLAY_BLOCK;
53
54         SYSIO_INTERFACE_ENTER;
55
56         /* need to read new data? */
57         rc = 0;
58         if (dir->cur >= dir->effective) {
59                 dir->cur = 0;
60                 dbase = (_OFF_T )dir->base;
61                 if (sizeof(dbase) != sizeof(dir->base) &&
62                     dbase != dir->base) {
63                         dir->effective = 0;
64                         SYSIO_INTERFACE_RETURN(NULL, -EOVERFLOW);
65                 }
66                 rc = _GETDIRENTRIES(dir->fd, 
67                                     dir->buf, 
68 #ifndef BSD
69                                     (size_t )BUFSIZE, 
70                                     (_OFF_T *) &dbase);
71 #else
72                                     (int )BUFSIZE, 
73                                     (long *) __restrict dbase);
74 #endif
75                 dir->base = (_SYSIO_OFF_T )dbase;
76
77                 /* error or end-of-file */
78                 if (rc == -ENOENT)
79                         rc = 0;
80                 if (rc <= 0) {
81                         dir->effective = 0;
82                         SYSIO_INTERFACE_RETURN(NULL, rc);
83                 }
84                 dir->effective = rc;
85         }
86         dp = (_DIRENT_T *)(dir->buf + dir->cur);
87
88 #ifdef _DIRENT_HAVE_D_RECLEN
89         dir->cur += dp->d_reclen;
90 #else
91         dir->cur += sizeof(_DIRENT_T);
92 #endif
93 #ifdef _DIRENT_HAVE_D_OFF
94         dir->filepos = dp->d_off;
95 #else
96         dir->filepos = dir->cur;
97 #endif
98
99         SYSIO_INTERFACE_RETURN(dp, 0);
100 }
101
102 sysio_sym_weak_alias(_READDIR, PREPEND(__,_READDIR))
103
104 int
105 _SCANDIR(const char *dirname, 
106          _DIRENT_T ***namelist, 
107          int (*filter) (const _DIRENT_T *), 
108          int (*compar) (const void *, const void *))
109 {
110         DIR *dir = NULL;
111         _DIRENT_T *de     = NULL,
112                   *nextde = NULL,
113                   **s     = NULL;
114         int n = 32, i = 0;
115         size_t desize;
116         SYSIO_INTERFACE_DISPLAY_BLOCK;
117
118         SYSIO_INTERFACE_ENTER;
119
120         if ((dir = SYSIO_INTERFACE_NAME(opendir)(dirname)) == NULL)
121                 SYSIO_INTERFACE_RETURN(-1, -errno);
122
123         while ((de = _READDIR(dir)) != NULL) {
124                 if ((filter == NULL) || filter(de)) {
125                         if (i == 0 || i >= n) {
126                             n = MAX(n, 2*i);
127                             s = (_DIRENT_T **)realloc(s, 
128                                 (size_t )(n * sizeof(_DIRENT_T *)));
129                             if (!s) 
130                                 SYSIO_INTERFACE_RETURN(-1, -ENOMEM);
131                         }
132                         desize = &de->d_name[_D_ALLOC_NAMLEN(de)] - (char * )de;
133                         nextde = (_DIRENT_T *)malloc(desize); 
134                         if (!nextde)
135                                 SYSIO_INTERFACE_RETURN(-1, -ENOMEM);
136
137                         s[i++] = (_DIRENT_T *)memcpy(nextde, de, desize);
138                 }
139         }
140         if (compar)
141                 qsort (s,
142                        i,
143                        sizeof (*s),
144                        (int (*)(const void *, const void *))compar);
145
146         *namelist = s;
147
148         SYSIO_INTERFACE_NAME(closedir)(dir);
149
150         SYSIO_INTERFACE_RETURN(i, 0);
151 }
152
153 sysio_sym_weak_alias(_SCANDIR, PREPEND(__,_SCANDIR))
154
155 #endif
156 #endif