1 /*
2  *  This program is free software; you can redistribute it and/or modify
3  *  it under the terms of the GNU General Public License as published by
4  *  the Free Software Foundation; either version 2 of the License, or
5  *  (at your option) any later version.
6  *
7  *  This program 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
10  *  GNU General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License
13  *  along with this program; if not, write to the Free Software
14  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15  */
16 
17 /* This file contains two versions of make_file_list(); one for Windows, and
18  * one for other systems (POSIX).
19  */
20 #ifdef WIN32
21 #include <io.h>
22 #include <ctype.h>
23 #include <string.h>
24 #include <malloc.h>
25 
26 char**
make_file_list(const char * pattern,int * pnum_entries)27 make_file_list (const char* pattern, int* pnum_entries)
28 {
29 	int num_entries, length;
30 	char** StringTable;
31 	char** lpLastOffs;
32 
33 	num_entries = 0;
34 	StringTable = 0;
35 	do
36 	{
37 		int slen;
38 		long handle;
39 		struct _finddata_t f;
40 
41 		if (num_entries == 0)
42 			length = 0;
43 		else
44 		{
45 			slen = (num_entries + 1) * sizeof (char*);
46 			StringTable = (char**) malloc (slen + length);
47 			if (StringTable == 0)
48 				break;
49 
50 			lpLastOffs = StringTable;
51 			*lpLastOffs = (char*)StringTable + slen;
52 
53 			num_entries = 0;
54 			length = slen;
55 		}
56 
57 		handle = _findfirst (pattern, &f);
58 		if (handle != -1)
59 		{
60 			do
61 			{
62 				if (f.attrib & (_A_HIDDEN | _A_SUBDIR | _A_SYSTEM))
63 					continue;
64 
65 				slen = strlen (f.name) + 1;
66 				length += slen;
67 
68 				if (StringTable)
69 				{
70 					char *lpStr;
71 					char **lpLo, **lpHi;
72 
73 					lpLo = StringTable;
74 					lpHi = lpLastOffs - 1;
75 					while (lpLo <= lpHi)
76 					{
77 						char c1, c2;
78 						char *pStr;
79 						int LocLen;
80 						char **lpMid;
81 
82 						lpMid = lpLo + ((lpHi - lpLo) >> 1);
83 
84 						LocLen = lpMid[1] - lpMid[0];
85 						if (LocLen > slen)
86 							LocLen = slen;
87 
88 						lpStr = lpMid[0];
89 						pStr = f.name;
90 						while (LocLen--
91 								&& (c1 = toupper (*lpStr++))
92 										== (c2 = toupper (*pStr++)))
93 							;
94 
95 						if (c1 <= c2)
96 							lpLo = lpMid + 1;
97 						else
98 							lpHi = lpMid - 1;
99 					}
100 
101 					lpStr = lpLo[0];
102 					memmove (lpStr + slen, lpStr, lpLastOffs[0] - lpLo[0]);
103 					strcpy (lpStr, f.name);
104 
105 					for (lpHi = lpLastOffs++; lpHi >= lpLo; --lpHi)
106 						lpHi[1] = lpHi[0] + slen;
107 				}
108 
109 				++num_entries;
110 
111 			} while (_findnext (handle, &f) == 0);
112 
113 			_findclose (handle);
114 		}
115 	} while (num_entries && StringTable == 0);
116 
117 	if (StringTable == 0)
118 		*pnum_entries = 0;
119 	else
120 		*pnum_entries = num_entries;
121 
122 	return StringTable;
123 }
124 
125 #else  /* ! defined(WIN32) */
126 
127 #include <sys/types.h>
128 #include <sys/stat.h>
129 #include <dirent.h>
130 #include <unistd.h>
131 #include <fnmatch.h>
132 #include <ctype.h>
133 #include <limits.h>
134 #include <string.h>
135 #include <malloc.h>
136 
137 char**
make_file_list(const char * pattern,int * pnum_entries)138 make_file_list (const char* pattern, int* pnum_entries)
139 {
140 	size_t num_entries, length;
141 	char** StringTable;
142 	char** lpLastOffs;
143 	char* slash;            // Pointer inside pattern to the last /
144 	char path[PATH_MAX];  // buffer for a filename with path
145 	char* file;             // Pointer inside path to the filename
146 	size_t pathlen;        // length of path, excluding last / and filename
147 
148 	slash = (char*) strrchr ((const char *) pattern, '/');
149 	if (slash == NULL)
150 	{
151 		pathlen = 1;
152 		path[0] = '.';
153 	}
154 	else
155 	{
156 		pathlen = slash - pattern;
157 		memcpy (path, pattern, pathlen);
158 		pattern = slash + 1;
159 	}
160 	file = path + pathlen + 1;
161 
162 	num_entries = 0;
163 	StringTable = 0;
164 	do
165 	{
166 		int slen;
167 		DIR *handle;
168 
169 		if (num_entries == 0)
170 			length = 0;
171 		else
172 		{
173 			slen = (num_entries + 1) * sizeof (char*);
174 			StringTable = (char**) malloc (slen + length);
175 			if (StringTable == 0)
176 				break;
177 
178 			lpLastOffs = StringTable;
179 			*lpLastOffs = (char*)StringTable + slen;
180 
181 			num_entries = 0;
182 			length = slen;
183 		}
184 
185 		path[pathlen] = '\0';  // strip any file part
186 		handle = opendir((const char *) path);
187 		if (handle != NULL)
188 		{
189 			path[pathlen] = '/';
190 					// change the 0 char to a slash; a filename will be
191 					// attached here.
192 			while (1)
193 			{
194 				struct dirent *de;
195 				struct stat sb;
196 
197 				de = readdir(handle);
198 				if (de == NULL)
199 					break;
200 				if (de->d_name[0] == '.')
201 					continue;
202 				strcpy (file, de->d_name);
203 						// attach the filename to path
204 				if (stat(path, &sb) == -1)
205 					continue;
206 				if (!S_ISREG(sb.st_mode))
207 					continue;
208 				if (fnmatch(pattern, de->d_name, 0) != 0)
209 					continue;
210 
211 				slen = strlen (de->d_name) + 1;
212 				length += slen;
213 
214 				if (StringTable)
215 				{
216 					char *lpStr;
217 					char **lpLo, **lpHi;
218 
219 					lpLo = StringTable;
220 					lpHi = lpLastOffs - 1;
221 					while (lpLo <= lpHi)
222 					{
223 						char c1, c2;
224 						char *pStr;
225 						int LocLen;
226 						char **lpMid;
227 
228 						lpMid = lpLo + ((lpHi - lpLo) >> 1);
229 
230 						LocLen = lpMid[1] - lpMid[0];
231 						if (LocLen > slen)
232 							LocLen = slen;
233 
234 						lpStr = lpMid[0];
235 						pStr = de->d_name;
236 						while (LocLen--
237 								&& (c1 = toupper (*lpStr++))
238 										== (c2 = toupper (*pStr++)))
239 							;
240 
241 						if (c1 <= c2)
242 							lpLo = lpMid + 1;
243 						else
244 							lpHi = lpMid - 1;
245 					}
246 
247 					lpStr = lpLo[0];
248 					memmove (lpStr + slen, lpStr, lpLastOffs[0] - lpLo[0]);
249 					strcpy (lpStr, de->d_name);
250 
251 					for (lpHi = lpLastOffs++; lpHi >= lpLo; --lpHi)
252 						lpHi[1] = lpHi[0] + slen;
253 				}
254 
255 				++num_entries;
256 			}
257 			closedir(handle);
258 		}
259 	} while (num_entries && StringTable == 0);
260 
261 	if (StringTable == 0)
262 		*pnum_entries = 0;
263 	else
264 		*pnum_entries = num_entries;
265 
266 	return StringTable;
267 }
268 
269 #endif
270 
271 void
free_file_list(char ** list)272 free_file_list (char** list)
273 {
274 	if (list)
275 		free(list);
276 }
277