Don't comment global content unless it is Conf
[geany-mirror.git] / ctags / main / portable-scandir.c
blob5e7c40061f88a9550e96135c0ba8290f7950ee61
1 #include "general.h"
2 /*
3 * Taken from https://github.com/ClusterLabs/pacemaker/blob/master/replace/scandir.c
4 */
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...
21 * --
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>
32 * -- Alan Robertson
33 * alanr@unix.sh
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>
41 * References: 1
44 * [Alan Robertson]
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 -
68 * scandir.c
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.
78 * /r$
80 * --
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,
104 * /r$
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)
115 #include <dirent.h>
116 #elif defined (HAVE_DIRENT_H) || defined (_MSC_VER)
117 # ifdef HAVE_DIRENT_H
118 # include <dirent.h>
119 # endif
120 #define USE_SCANDIR_COMPARE_STRUCT_DIRENT
122 #include <sys/types.h>
124 #include <stdlib.h>
125 #include <stddef.h>
126 #include <string.h>
128 #ifndef NULL
129 # define NULL ((void *) 0)
130 #endif
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 **)
141 #else
142 /* This is what the linux header file says ... */
143 int (*compare_function) (const void *, const void *)
144 #endif
147 DIR *directory;
148 struct dirent **array;
149 struct dirent *entry;
150 struct dirent *copy;
151 int allocated = INITIAL_ALLOCATION;
152 int counter = 0;
154 /* Get initial list space and open directory. */
156 if (directory = opendir(directory_name), directory == NULL)
157 return -1;
159 if (array = (struct dirent **)eMalloc(allocated * sizeof(struct dirent *)), array == NULL)
160 return -1;
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:
172 * "char d_name[1];"
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 */
185 int extra = 0;
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) {
193 closedir(directory);
194 eFree(array);
195 return -1;
197 copy->d_ino = entry->d_ino;
198 copy->d_reclen = entry->d_reclen;
199 strcpy(copy->d_name, entry->d_name);
201 /* Save the copy. */
203 if (counter + 1 == allocated) {
204 allocated <<= 1;
205 array = (struct dirent **)
206 eRealloc((char *)array, allocated * sizeof(struct dirent *));
207 if (array == NULL) {
208 closedir(directory);
209 eFree(array);
210 eFree(copy);
211 return -1;
214 array[counter++] = copy;
217 /* Close things off. */
219 array[counter] = NULL;
220 *array_pointer = array;
221 closedir(directory);
223 /* Sort? */
225 if (counter > 1 && compare_function)
226 qsort((char *)array, counter, sizeof(struct dirent *)
227 , (int (*)(const void *, const void *))(compare_function));
229 return counter;
231 #endif
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);
240 #endif