The Pedigree Project  0.1
glue-scandir.c
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #ifndef HAVE_OPENDIR
21 
22 /*
23  * Copyright (c) 1983 Regents of the University of California.
24  * All rights reserved.
25  *
26  * Redistribution and use in source and binary forms, with or without
27  * modification, are permitted provided that the following conditions
28  * are met:
29  * 1. Redistributions of source code must retain the above copyright
30  * notice, this list of conditions and the following disclaimer.
31  * 2. Redistributions in binary form must reproduce the above copyright
32  * notice, this list of conditions and the following disclaimer in the
33  * documentation and/or other materials provided with the distribution.
34  * 3. All advertising materials mentioning features or use of this software
35  * must display the following acknowledgement:
36  * This product includes software developed by the University of
37  * California, Berkeley and its contributors.
38  * 4. Neither the name of the University nor the names of its contributors
39  * may be used to endorse or promote products derived from this software
40  * without specific prior written permission.
41  *
42  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52  * SUCH DAMAGE.
53  */
54 
55 #if defined(LIBC_SCCS) && !defined(lint)
56 static char sccsid[] = "@(#)scandir.c 5.10 (Berkeley) 2/23/91";
57 #endif /* LIBC_SCCS and not lint */
58 
59 /*
60  * Scan the directory dirname calling select to make a list of selected
61  * directory entries then sort using qsort and compare routine dcomp.
62  * Returns the number of entries and a pointer to a list of pointers to
63  * struct dirent (through namelist). Returns -1 if there were any errors.
64  */
65 
66 #include <newlib.h>
67 
68 #include <dirent.h>
69 #include <stdlib.h>
70 #include <string.h>
71 #include <sys/stat.h>
72 #include <sys/types.h>
73 
74 /*
75  * The DIRSIZ macro gives the minimum record length which will hold
76  * the directory entry. This requires the amount of space in struct dirent
77  * without the d_name field, plus enough space for the name with a terminating
78  * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
79  */
80 #undef DIRSIZ
81 #ifdef _DIRENT_HAVE_D_NAMLEN
82 #define DIRSIZ(dp) \
83  ((sizeof(struct dirent) - (MAXNAMLEN + 1)) + \
84  (((dp)->d_namlen + 1 + 3) & ~3))
85 #else
86 #define DIRSIZ(dp) \
87  ((sizeof(struct dirent) - (MAXNAMLEN + 1)) + \
88  ((strlen((dp)->d_name) + 1 + 3) & ~3))
89 #endif
90 
91 #ifndef __P
92 #define __P(args) ()
93 #endif
94 
95 int scandir(dirname, namelist, select, dcomp) const char *dirname;
96 struct dirent ***namelist;
97 int(*select) __P((struct dirent *) );
98 int(*dcomp) __P((const void *, const void *) );
99 {
100  register struct dirent *d, *p, **names;
101  register size_t nitems;
102  struct stat stb;
103  size_t arraysz;
104  DIR *dirp;
105 
106  if ((dirp = opendir(dirname)) == NULL)
107  return (-1);
108  if (fstat(dirp->fd, &stb) < 0)
109  return (-1);
110 
111  /*
112  * estimate the array size by taking the size of the directory file
113  * and dividing it by a multiple of the minimum size entry.
114  */
115  arraysz = (stb.st_size / 24);
116  names = (struct dirent **) malloc(arraysz * sizeof(struct dirent *));
117  if (names == NULL)
118  return (-1);
119 
120  nitems = 0;
121  while ((d = readdir(dirp)) != NULL)
122  {
123  if (select != NULL && !(*select)(d))
124  continue; /* just selected names */
125  /*
126  * Make a minimum size copy of the data
127  */
128  p = (struct dirent *) malloc(DIRSIZ(d));
129  if (p == NULL)
130  return (-1);
131  p->d_ino = d->d_ino;
132 // p->d_reclen = d->d_reclen;
133 #ifdef _DIRENT_HAVE_D_NAMLEN
134  p->d_namlen = d->d_namlen;
135  bcopy(d->d_name, p->d_name, p->d_namlen + 1);
136 #else
137  strcpy(p->d_name, d->d_name);
138 #endif
139  /*
140  * Check to make sure the array has space left and
141  * realloc the maximum size.
142  */
143  if (++nitems >= arraysz)
144  {
145  if (fstat(dirp->fd, &stb) < 0)
146  return (-1); /* just might have grown */
147  arraysz = stb.st_size / 12;
148  names = (struct dirent **) realloc(
149  (char *) names, arraysz * sizeof(struct dirent *));
150  if (names == NULL)
151  return (-1);
152  }
153  names[nitems - 1] = p;
154  }
155  closedir(dirp);
156  if (nitems && dcomp != NULL)
157  qsort(names, nitems, sizeof(struct dirent *), dcomp);
158  *namelist = names;
159  return (nitems);
160 }
161 
162 /*
163  * Alphabetic order comparison routine for those who want it.
164  */
165 int alphasort(d1, d2) const struct dirent **d1;
166 const struct dirent **d2;
167 {
168  return (strcmp((*d1)->d_name, (*d2)->d_name));
169 }
170 
171 #endif /* ! HAVE_OPENDIR */