1 /*
2 * $Id: scandir.c,v 1.5 2002-12-22 17:36:26 f Exp $
3 */
4
5 #include "irc.h"
6 #include "ircaux.h"
7
8 #ifndef HAVE_SCANDIR
9
10 #if (!defined(ultrix) && !defined(__386BSD__) && !defined(_HPUX_SOURCE)) || defined(HPUX7)
11
12 /*
13 * Copyright (c) 1983 Regents of the University of California. All rights
14 * reserved.
15 *
16 * Redistribution and use in source and binary forms are permitted provided that
17 * the above copyright notice and this paragraph are duplicated in all such
18 * forms and that any documentation, advertising materials, and other
19 * materials related to such distribution and use acknowledge that the
20 * software was developed by the University of California, Berkeley. The
21 * name of the University may not be used to endorse or promote products
22 * derived from this software without specific prior written permission. THIS
23 * SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
24 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
25 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
26 */
27
28 # if defined(LIBC_SCCS) && !defined(lint)
29 static char sccsid[] = "@(#)scandir.c 5.3 (Berkeley) 6/18/88";
30 # endif /* LIBC_SCCS and not lint */
31
32 # ifndef NULL
33 # define NULL 0
34 # endif
35
36 /*
37 * Scan the directory dirname calling select to make a list of selected
38 * directory entries then sort using qsort and compare routine dcomp. Returns
39 * the number of entries and a pointer to a list of pointers to struct direct
40 * (through namelist). Returns -1 if there were any errors.
41 */
42
43 /*
44 * Mike Sandrof added this for HPUX compatibility in
45 * IRCII on the advice of some HPUX users - 5/11/90
46 * this is no longer valid, as hpux has its own scandir(), june 1993, phone.
47 * at least, for some versions of hpux.. oct 1994, mrg.
48 *
49 * Brett Sivies added POSIX here.
50 */
51
52 # if defined(XD88) || defined(__SVR4) || defined(POSIX) || defined(__linux__) \
53 || defined(SVR3) || defined(__osf__) || defined(M_UNIX) || defined(_SEQUENT_) \
54 || defined(__QNX__)
55
56 /*
57 ** SCANDIR
58 ** Scan a directory, collecting all (selected) items into a an array.
59 */
60 #include "scandir.h"
61
62 int
scandir(Name,dirlist,Selector,Sorter)63 scandir(Name, dirlist, Selector, Sorter)
64 #if defined(__linux__) || defined(__sgi)
65 const char *Name;
66 #else
67 char *Name;
68 #endif
69 struct dirent ***dirlist;
70 int (*Selector)();
71 int (*Sorter)();
72 {
73 struct dirent **names;
74 static struct dirent *E;
75 register DIR *Dp;
76 register int i;
77 register int size = INITIAL_SIZE;
78
79 if (!(names = (struct dirent **) new_malloc(size * sizeof names[0])) || access(Name, R_OK | X_OK) || !(Dp = opendir(Name)))
80 return(-1);
81
82 /* Read entries in the directory. */
83
84 for (i = 0; (E = readdir(Dp)); )
85 if (Selector == NULL || (*Selector)(E))
86 {
87 /* User wants them all, or he wants this one. */
88 if (++i >= size)
89 {
90 size <<= 1;
91 names = (struct dirent **) new_realloc((char *)names, size * sizeof names[0]);
92 if (names == NULL)
93 {
94 closedir(Dp);
95 new_free(&names);
96 return(-1);
97 }
98 }
99
100 /* Copy the entry. */
101 if ((names[i - 1] = (struct dirent *) new_malloc(DIRSIZ(E))) == NULL)
102 {
103 closedir(Dp);
104 new_free(&names);
105 return(-1);
106 }
107 #ifndef __QNX__
108 names[i - 1]->d_ino = E->d_ino;
109 names[i - 1]->d_reclen = E->d_reclen;
110 #endif
111 (void) strcpy(names[i - 1]->d_name, E->d_name);
112 }
113
114 /* Close things off. */
115 names = (struct dirent **) new_realloc((char *) names, (i + 1) * sizeof names[0]);
116 names[i] = 0;
117 *dirlist = names;
118 closedir(Dp);
119
120 /* Sort? */
121 if (i && Sorter)
122 qsort((char *)names, i, sizeof names[0], Sorter);
123
124 return(i);
125 }
126
127 /**************************** Patched by Flier ******************************/
128 /*
129 * Alphabetic order comparison routine for those who want it.
130 */
131 #ifndef alphasort
alphasort(d1,d2)132 int alphasort(d1, d2)
133 struct dirent **d1, **d2;
134 {
135 return(strcmp((*d1)->d_name, (*d2)->d_name));
136 }
137 #endif
138 /****************************************************************************/
139
140 #else
141 /* End of Mike Sandrof's change */
142 #include "scandir.h"
143
scandir(dirname,namelist,select,dcomp)144 int scandir(dirname, namelist, select, dcomp)
145 #ifdef NeXT
146 const char *dirname;
147 #else
148 char *dirname;
149 #endif /* NeXT */
150 struct direct *(*namelist[]);
151 int (*select) (), (*dcomp) ();
152 {
153 register struct direct *d,
154 *p,
155 **names;
156 register int nitems;
157 register char *cp1,
158 *cp2;
159 struct stat stb;
160 long arraysz;
161 DIR *dirp;
162
163 if (access(dirname, R_OK|X_OK))
164 return (-1);
165 if ((dirp = opendir(dirname)) == NULL)
166 return (-1);
167 if (fstat(dirp->dd_fd, &stb) < 0)
168 return (-1);
169
170 /*
171 * estimate the array size by taking the size of the directory file and
172 * dividing it by a multiple of the minimum size entry.
173 */
174 arraysz = (stb.st_size / 24);
175 names = (struct direct **) new_malloc(arraysz * sizeof(struct direct *));
176 if (names == NULL)
177 return (-1);
178
179 nitems = 0;
180 while ((d = readdir(dirp)) != NULL)
181 {
182 if (select != NULL && !(*select) (d))
183 continue; /* just selected names */
184 /*
185 * Make a minimum size copy of the data
186 */
187 p = (struct direct *) new_malloc(DIRSIZ(d));
188 if (p == NULL)
189 return (-1);
190 p->d_ino = d->d_ino;
191 p->d_reclen = d->d_reclen;
192 # if ! defined(ISC22) && ! defined(ESIX)
193 p->d_namlen = d->d_namlen;
194 # endif /* ! defined(ISC22) && ! defined(ESIX) */
195 for (cp1 = p->d_name, cp2 = d->d_name; *cp1++ = *cp2++;);
196 /*
197 * Check to make sure the array has space left and realloc the
198 * maximum size.
199 */
200 if (++nitems >= arraysz)
201 {
202 if (fstat(dirp->dd_fd, &stb) < 0)
203 return (-1); /* just might have grown */
204 arraysz = stb.st_size / 12;
205 names = (struct direct **) new_realloc((char *) names,
206 arraysz * sizeof(struct direct *));
207 if (names == NULL)
208 return (-1);
209 }
210 names[nitems - 1] = p;
211 }
212 closedir(dirp);
213 if (nitems && dcomp != NULL)
214 qsort(names, nitems, sizeof(struct direct *), dcomp);
215 *namelist = names;
216 return (nitems);
217 }
218
219
220 /*
221 * Alphabetic order comparison routine for those who want it.
222 */
alphasort(d1,d2)223 int alphasort(d1, d2)
224 struct direct **d1,
225 **d2;
226 {
227 return (strcmp((*d1)->d_name, (*d2)->d_name));
228 }
229 #endif
230
231 #endif /* ultrix || __386BSD__ || BSD */
232 #endif /* !HAVE_SCANDIR */
233