3 * Taken from https://github.com/ClusterLabs/pacemaker/blob/master/replace/scandir.c
6 /* scandir: Scan a directory, collecting all (selected) items into a an array.
8 * This code borrowed from 'libit', which can be found here:
10 * http://www.iro.umontreal.ca/~pinard/libit/dist/scandir/
12 * The original author put this code in the public domain.
13 * It has been modified slightly to get rid of warnings, etc.
15 * Below is the email I received from pinard@iro.umontreal.ca (François Pinard)
16 * when I sent him an email asking him about the license, etc. of this
17 * code which I obtained from his site.
19 * I think the correct spelling of his name is Rich Salz. I think he's now
20 * rsalz@datapower.com...
22 * Rich Salz, Chief Security Architect
23 * DataPower Technology http://www.datapower.com
24 * XS40 XML Security Gateway http://www.datapower.com/products/xs40.html
26 * Copyright(C): none (public domain)
27 * License: none (public domain)
28 * Author: Rich Salz <rsalz@datapower.com>
35 **************************************************************************
37 * Subject: Re: Scandir replacement function
38 * Date: 18 May 2001 12:00:48 -0400
39 * From: pinard@iro.umontreal.ca (François Pinard)
40 * To: Alan Robertson <alanr@unix.sh>
46 * > Hi, I'd like to use your scandir replacement function found here:
47 * > http://www.iro.umontreal.ca/~pinard/libit/dist/scandir/ But, it does
48 * > not indicate authorship or licensing terms in it. Could you tell me
49 * > who wrote this code, under what license you distribute it, and whether
50 * > and under what terms I may further distribute it?
52 * Hello, Alan. These are (somewhat) explained in UNSHAR.HDR found in the
53 * same directory. The routines have been written by Rick Saltz (I'm not
54 * completely sure of the spelling) a long while ago. I think that nowadays,
55 * Rick is better known as the main author of the nice INN package.
57 **************************************************************************
59 * I spent a little time verifying this with Rick Salz.
60 * The results are below:
62 **************************************************************************
64 * Date: Tue, 20 Sep 2005 21:52:09 -0400 (EDT)
65 * From: Rich Salz <rsalz@datapower.com>
66 * To: Alan Robertson <alanr@unix.sh>
67 * Subject: Re: Verifying permissions/licenses/etc on some old code of yours -
69 * In-Reply-To: <433071CA.8000107@unix.sh>
70 * Message-ID: <Pine.LNX.4.44L0.0509202151270.9198-100000@smtp.datapower.com>
71 * Content-Type: TEXT/PLAIN; charset=US-ASCII
73 * yes, it's most definitely in the public domain.
75 * I'm glad you find it useful. I'm surprised it hasn't been replaced by,
76 * e.g,. something in GLibC. Ii'm impressed you tracked me down.
81 * Rich Salz Chief Security Architect
82 * DataPower Technology http://www.datapower.com
83 * XS40 XML Security Gateway http://www.datapower.com/products/xs40.html
84 * ---------------------------------------------------------------------->
85 * Subject: scandir, ftw REDUX
86 * Date: 1 Jan 88 00:47:01 GMT
87 * From: rsalz@pebbles.bbn.com
88 * Newsgroups: comp.sources.misc
91 * Forget my previous message -- I just decided for completeness's sake to
92 * implement the SysV ftw(3) routine, too.
94 * To repeat, these are public-domain implementations of the SystemV ftw()
95 * routine, the BSD scandir() and alphasort() routines, and documentation for
96 * same. The FTW manpage could be more readable, but so it goes.
98 * Anyhow, feel free to post these, and incorporate them into your existing
99 * packages. I have readdir() routiens for MSDOS and the Amiga if anyone
100 * wants them, and should have them for VMS by the end of January; let me
101 * know if you want copies.
103 * Yours in filesystems,
106 * Anyhow, feel free to post
107 * ----------------------------------------------------------------------<
111 #include "routines.h"
112 #include "routines_p.h"
114 #if defined (HAVE_SCANDIR) && defined (HAVE_DIRENT_H)
116 #elif defined (HAVE_DIRENT_H) || defined (_MSC_VER)
117 # ifdef HAVE_DIRENT_H
120 #define USE_SCANDIR_COMPARE_STRUCT_DIRENT
122 #include <sys/types.h>
129 # define NULL ((void *) 0)
132 /* Initial guess at directory allocated. */
133 #define INITIAL_ALLOCATION 20
136 scandir(const char *directory_name
,
137 struct dirent
***array_pointer
, int (*select_function
) (const struct dirent
*),
138 #ifdef USE_SCANDIR_COMPARE_STRUCT_DIRENT
139 /* This is what the linux man page says */
140 int (*compare_function
) (const struct dirent
**, const struct dirent
**)
142 /* This is what the linux header file says ... */
143 int (*compare_function
) (const void *, const void *)
148 struct dirent
**array
;
149 struct dirent
*entry
;
151 int allocated
= INITIAL_ALLOCATION
;
154 /* Get initial list space and open directory. */
156 if (directory
= opendir(directory_name
), directory
== NULL
)
159 if (array
= (struct dirent
**)eMalloc(allocated
* sizeof(struct dirent
*)), array
== NULL
)
162 /* Read entries in the directory. */
164 while (entry
= readdir(directory
), entry
)
165 if (select_function
== NULL
|| (*select_function
) (entry
)) {
166 /* User wants them all, or he wants this one. Copy the entry. */
169 * On some OSes the declaration of "entry->d_name" is a minimal-length
170 * placeholder. Example: Solaris:
171 * /usr/include/sys/dirent.h:
173 * man page "dirent(3)":
174 * The field d_name is the beginning of the character array
175 * giving the name of the directory entry. This name is
176 * null terminated and may have at most MAXNAMLEN chars.
177 * So our malloc length may need to be increased accordingly.
178 * sizeof(entry->d_name): space (possibly minimal) in struct.
179 * strlen(entry->d_name): actual length of the entry.
181 * John Kavadias <john_kavadias@hotmail.com>
182 * David Lee <t.d.lee@durham.ac.uk>
184 int namelength
= strlen(entry
->d_name
) + 1; /* length with NULL */
187 if (sizeof(entry
->d_name
) <= namelength
) {
188 /* allocated space <= required space */
189 extra
+= namelength
- sizeof(entry
->d_name
);
192 if (copy
= (struct dirent
*)eMalloc(sizeof(struct dirent
) + extra
), copy
== NULL
) {
197 copy
->d_ino
= entry
->d_ino
;
198 copy
->d_reclen
= entry
->d_reclen
;
199 strcpy(copy
->d_name
, entry
->d_name
);
203 if (counter
+ 1 == allocated
) {
205 array
= (struct dirent
**)
206 eRealloc((char *)array
, allocated
* sizeof(struct dirent
*));
214 array
[counter
++] = copy
;
217 /* Close things off. */
219 array
[counter
] = NULL
;
220 *array_pointer
= array
;
225 if (counter
> 1 && compare_function
)
226 qsort((char *)array
, counter
, sizeof(struct dirent
*)
227 , (int (*)(const void *, const void *))(compare_function
));
233 #if defined (HAVE_DIRENT_H) || defined (_MSC_VER)
234 int scanDirectory (const char *directory_name
,
235 struct dirent
***array_pointer
, int (*select_function
) (const struct dirent
*),
236 int (*compare_function
) (const struct dirent
**, const struct dirent
**))
238 return scandir (directory_name
, array_pointer
, select_function
, compare_function
);